首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法在内存OLTP中恢复索引未使用内存

无法在内存OLTP中恢复索引未使用内存
EN

Database Administration用户
提问于 2020-09-14 13:05:02
回答 2查看 423关注 0票数 6

重现问题的步骤

创建一个具有内存优化的文件组和容器的数据库,只在内存中创建模式,使用非集群pk模拟插入和删除活动。我的结果是,我有高索引,未使用的内存,不会下降。

代码语言:javascript
复制
 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

当我在本地机器Microsoft 2017 (RTM) (KB4505224) - 14.0.2027.2 (X64)开发者版上运行16 GB最大内存和1.5GB可用内存时,memory_allocated_for_indexes_kb会正常波动。

当我在我们的DEV环境下运行它时,Microsoft 2019 (RTM-CU7) (KB4570012) - 15.0.4063.15 (X64)企业版2 TB最大内存,220 GB可用内存

memory_allocated_for_indexes_kb只生长。我已经为一个表模拟了几个小时的活动,索引使用内存=0.24MB,索引未使用内存= 385 MB,它不会下降。

垃圾收集器根据XTP垃圾收集中已删除/秒的PerfMon清除过期行运行。

我在某个地方读到,垃圾收集器在面临内存压力之前不会释放空间,但似乎奇怪的是,垃圾收集器会保存这么多未使用的内存。

编辑:我使用资源池作为存储内存表的数据库.百分之一是我能去的最低的。我在内存中填充了另一个表,占用了99%的资源池,memory_allocated_for_indexes仍然不会下降。是否存在事务活动。没有有效的操作阻止GC,我已经等了30多分钟了。

我不能接受当前的任何一个答案,因为我的问题仍然没有答案。请注意,表行被清除,但对索引没有清除。

EN

回答 2

Database Administration用户

发布于 2020-09-14 14:25:49

我在某个地方读到,垃圾收集器在面临内存压力之前不会释放空间,但似乎奇怪的是,垃圾收集器会保存这么多未使用的内存。

但这很奇怪吗?当垃圾收集可以推迟到以后时,为什么现在要进行垃圾收集:)

文档,确认你的想法(强调我的):

用户事务提交后,它将标识与其运行的调度程序关联的所有排队项,然后释放内存。如果调度程序上的垃圾收集队列为空,它将搜索当前NUMA节点中的任何非空队列。如果存在较低的事务活动和内存压力,则主垃圾收集线程可以访问任意队列中的垃圾收集行。如果在删除大量行之后没有事务活动,并且没有内存压力,则在事务活动恢复或内存压力存在之前,将不会垃圾收集已删除的行。

您的测试工作量似乎相当小,如果不足以触发任何集合,我也不会感到惊讶,特别是考虑到该系统的内存资源是多么健壮。

有了2TB的内存,我不会为这个目的花费少于500 of的内存,也不会担心这一点,直到它成为一个实际的问题。

票数 5
EN

Database Administration用户

发布于 2020-09-16 19:11:14

您正在运行Enterprise,因此您应该创建一个资源池,以便缓冲池不受in-mem增长的影响。

详情如下:

http://nedotter.com/archive/2016/12/monitoring-in-memory-oltp-resource-pools/

票数 0
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/275494

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档