Zik*_*ato 6 sql-server memory memory-optimized-tables sql-server-2019
重现问题的步骤
创建具有内存优化文件组和容器的数据库 使用非集群 pk 创建仅模式内存表 模拟插入和删除活动。我的结果是我有高索引未使用的内存,不会下降。
USE master
go
DROP DATABASE IF EXISTS MemoryOptimizedTest
CREATE DATABASE MemoryOptimizedTest
GO
USE MemoryOptimizedTest
GO
ALTER DATABASE MemoryOptimizedTest
ADD FILEGROUP imoltp_mod CONTAINS MEMORY_OPTIMIZED_DATA
GO
ALTER DATABASE MemoryOptimizedTest ADD FILE (name='imoltp_mod1', filename='c:\imoltp_mod1') TO FILEGROUP imoltp_mod
GO
DROP TABLE IF EXISTS dbo.MyCache
CREATE TABLE dbo.MyCache
(
PK int NOT NULL,
SecondInt int NOT NULL,
ThirdInt int NOT NULL,
CONSTRAINT PK_MyCache PRIMARY KEY NONCLUSTERED (PK)
) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY)
go
/* Generate activity and monitor table size */
USE MemoryOptimizedTest
go
SELECT
object_id,
OBJECT_SCHEMA_NAME(object_id) + '.' + OBJECT_NAME(object_id) AS Table_Name,
memory_allocated_for_table_kb,
memory_used_by_table_kb,
memory_allocated_for_indexes_kb,
memory_used_by_indexes_kb
FROM sys.dm_db_xtp_table_memory_stats
WHERE OBJECT_ID = OBJECT_ID('dbo.MyCache')
;WITH
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 CROSS JOIN L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 CROSS JOIN L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 CROSS JOIN L2 AS B),
L4 AS(SELECT 1 AS c FROM L3 CROSS JOIN L3 AS B),
L5 AS(SELECT 1 AS c FROM L4 CROSS JOIN L4 AS B),
Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS n FROM L5)
, tally AS (SELECT TOP (10000) n FROM Nums ORDER BY n)
INSERT INTO dbo.MyCache (PK, SecondInt, ThirdInt)
SELECT
n
, n+1
, n+2
FROM tally
WAITFOR DELAY '00:00:02'
DELETE FROM dbo.MyCache
GO 50
Run Code Online (Sandbox Code Playgroud)
当我在具有 16 GB 最大内存和 1.5 GB 可用内存的本地计算机 Microsoft SQL Server 2017 (RTM-GDR) (KB4505224) - 14.0.2027.2 (X64) Developer Edition 上运行它时,memory_alulated_for_indexes_kb 正常波动。
当我在开发环境 Microsoft SQL Server 2019 (RTM-CU7) (KB4570012) - 15.0.4063.15 (X64) Enterprise Edition 2 TB 最大内存,220 GB 可用内存上运行它时
memory_alated_for_indexes_kb 只会增长。我已经模拟了表的活动几个小时,并且索引已用内存 = 0.24 MB,索引未使用内存 = 385 MB,并且它不会下降。
垃圾收集器根据 XTP 垃圾收集中的 PerfMon Sweep 每秒删除的过期行数运行。
我在某处读到,垃圾收集器在面临内存压力之前不会释放空间,但它会保留这么多未使用的内存,这似乎很奇怪。
编辑:我使用资源池作为保存内存表的数据库。百分之一是我能达到的最低水平。我用另一个表填充了内存,占用了资源池的 99%,但内存分配的索引仍然不会下降。是否有交易活动。没有任何活动事务会阻塞 GC,我已经等待了 30 多分钟。
我无法接受任何当前答案,因为我的问题仍未得到解答。请注意,表行已被清理,但索引并未被清理。
我在某处读到,垃圾收集器在面临内存压力之前不会释放空间,但它会保留这么多未使用的内存,这似乎很奇怪。
不过,这很奇怪吗?为什么现在要进行垃圾收集,因为它可以推迟到以后:)
从文档中,确认了您的想法(强调我的):
用户事务提交后,它会识别与其运行的调度程序关联的所有排队项目,然后释放内存。如果调度程序上的垃圾收集队列为空,它将在当前 NUMA 节点中搜索任何非空队列。如果事务活动较低并且存在内存压力,则主垃圾收集线程可以访问任何队列中的垃圾收集行。如果(例如)删除大量行后没有事务活动并且没有内存压力,则删除的行将不会被垃圾收集,直到事务活动恢复或存在内存压力。
您的测试工作负载似乎很小,如果它不足以触发任何收集,我不会感到惊讶,特别是考虑到该系统的内存资源有多强大。
有了 2TB 内存,我不会为此目的而使用 < 500MB 的内存,也不会担心这一点,直到它成为一个实际问题。