CREATE PROC GetStats
AS
SELECT *
FROM sys.dm_db_xtp_table_memory_stats
WHERE object_id = object_id('dbo.Test')
SELECT name AS 'index_name',
s.*
FROM sys.dm_db_xtp_hash_index_stats s
JOIN sys.indexes i
ON s.object_id = i.object_id
AND s.index_id = i.index_id
WHERE i.object_id = object_id('dbo.Test')
SELECT name AS 'index_name',
s.index_id,
scans_started,
rows_returned,
rows_expired,
rows_expired_removed
FROM sys.dm_db_xtp_index_stats s
JOIN sys.indexes i
ON s.object_id = i.object_id
AND s.index_id = i.index_id
WHERE object_id('dbo.Test') = s.object_id;
然后运行以下命令,尝试切换ROLLBACK和COMMIT
CREATE TABLE [dbo].[Test]
(
[Id] [INT] NOT NULL CONSTRAINT PK PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 8),
[String] CHAR(900) COLLATE Latin1_General_100_BIN2 NOT NULL INDEX IX NONCLUSTERED HASH WITH (BUCKET_COUNT = 8)
) WITH ( MEMORY_OPTIMIZED = ON )
INSERT INTO [dbo].[Test]
VALUES
(1,REPLICATE('A',900)),
(2,REPLICATE('A',900)),
(3,REPLICATE('A',900)),
(4,REPLICATE('A',900)),
(5,REPLICATE('A',900)),
(6,REPLICATE('A',900)),
(7,REPLICATE('A',900)),
(8,REPLICATE('A',900))
/*Get initial position*/
EXEC GetStats
BEGIN TRAN
UPDATE [dbo].[Test]
SET [String] = REPLICATE('B', 900)
/*Mid Transaction*/
EXEC GetStats
COMMIT
/*Force a scan of both indexes*/
SELECT COUNT(*)
FROM dbo.Test WITH (INDEX=IX)
EXCEPT
SELECT COUNT(*)
FROM dbo.Test WITH (INDEX = PK)
EXEC GetStats
DROP TABLE [dbo].[Test]
我对 SIGMOD 论文Hekaton 的理解:SQL Server 的内存优化 OLTP 引擎是它与其他类型的垃圾一样得到处理。
几个相关部分是
请注意,它说无效而不是垃圾收集。
另请参阅垃圾收集部分(强调我的)
但在实践中,回滚产生的垃圾似乎比提交更快地被分配,所以也许中止线程至少在某些时候确实清理了自己的垃圾。
为了看到这一点,我创建了以下过程(在内存优化数据库中)
然后运行以下命令,尝试切换
ROLLBACK
和COMMIT
我一直得到如下总结的结果。
UPDATE
对于提交和回滚事务的影响相同memory_allocated_for_table_kb
(从 7KB 增加到 15KB)桶统计
两个测试的初始桶统计数据与
中间事务(在回滚或提交之前)桶计数是
之后,
rollback
它们立即恢复到初始计数,但之后commit
它们仍保持在第二个表中,表明现在存在垃圾。显然所有 PK 值散列到的单个桶现在有 16 个链接行,而不是以前的 8 个。
现在另一列的哈希索引有两个桶在使用,每个桶有 8 个链接行(对于 和 的“之前”和“之后”字符串
AAA...
值BBB...
)行已过期
提交后
回滚后
在这两种情况下都是,但是
rows_expired
在事务提交之后,而在回滚之后所有这些都被删除了。8
rows_expired_removed
0