我有一个包含两个表的数据库。一个表大约有 2000 万行,另一个表大约有 7000 万行。
当我在这两个表上运行 sp_spaceused 时,我发现数据的总大小为 ~6.7GB,索引的总大小为 ~2.6GB。加起来总共约 9.3GB。
这是该服务器上唯一的数据。
我是 SQL 新手,所以我假设在整个数据集和索引加载到内存后,这两个表将占用的 RAM 量接近 9.3GB。但我显然大错特错,因为在运行查询几分钟后,SQL Server 进程占用的内存将达到 30+GB 并继续攀升。我什至测试过一遍又一遍地运行相同的查询,并且占用的内存量继续攀升。
RAM 过多的原因是数据的最终大小将是此大小的 5-6 倍,这将用于数据分析。
我的问题是为什么 SQL Server 使用这么多内存?如果整个表和索引都加载到内存中,它继续加载到内存中的是什么?有什么办法可以控制这个吗?如果我的目标是内存分析,除了非聚集索引之外,还有其他类型的索引可以使用吗?我一直在阅读列存储索引,但在对较小的数据集进行测试后,与使用列存储索引相比,我实际上能够通过完全删除索引来获得更好的性能。
总的来说,我对这台服务器发生了什么感到困惑。任何人都可以提供一些指导吗?目前我正在尝试测试 SQL Server 2014,但它仍在 CPT2 中,因此在发布之前它不是解决方案。
我还研究了基于列的存储技术,例如 Amazon Redshift,但它们的服务不符合 HIPAA 标准。
在这个问题上,我发现了一些要运行的查询。我现在数据库的缓存大小是 32230.390625。这大于数据库总大小的 3 倍。
db_buffer_pages = 4125490
db_buffer_MB = 32230
Run Code Online (Sandbox Code Playgroud)
我还想做一些测试,并决定完全擦除数据库,重新启动 SQL 服务,并重新加载数据。当我这样做时,它使用了大约 20 GB 的 RAM。我不明白为什么。这是原始数据和索引大小的两倍多。
swa*_*eck 11
正如引用的答案中所述,SQL Server 将使用您允许使用的内存。此外,SQL Server 将内存用于与“数据存储”域隔离的各种事物。除了mrdenny注意到的东西,它还缓存了一个查询的查询计划
在 SQL Server 中,内存使用由内存管理员跟踪。看看有多少:
SELECT *
FROM sys.dm_os_memory_clerks;
Run Code Online (Sandbox Code Playgroud)
这些大致可以分为四类:
SQL Server 协调内存请求的方式是通过所谓的内存代理。
SELECT *
FROM sys.dm_os_memory_brokers;
Run Code Online (Sandbox Code Playgroud)
这些代理负责管理内存。当遇到压力时,CACHE 代理会第一个向系统释放内存。这意味着在您的数据页从缓冲池中刷新之前,您的查询计划将从内存中驱逐。(以上大部分内容摘自 Bob Ward 在 2013 年 PASS 峰会上的记忆报告)。
这只是一个简短的概述。不仅仅是这个,但现实情况是,您的系统中发生了很多事情,因此假设 SQL Server 没有正确处理内存只是因为您的磁盘大小值是不太正确的数据库不小于或等于 的值buffer pages*8/1024
。
这是另一个列出缓冲对象的查询,只是为了好玩。
SELECT
object_sysname = OBJECT_NAME(p.[object_id]),
index_id = p.index_id,
buffer_size_mb = COUNT(*)/128.,
buffer_count = COUNT(*),
compression_type = p.data_compression_desc,
allocation_type_desc = a.type_desc,
rows = p.[rows]
FROM sys.allocation_units AS a
INNER JOIN sys.dm_os_buffer_descriptors AS b
ON a.allocation_unit_id = b.allocation_unit_id
INNER JOIN sys.partitions AS p
ON a.container_id = p.partition_id
WHERE b.database_id = CONVERT(int,DB_ID())
AND p.[object_id] > 100
GROUP BY p.[object_id], p.index_id,
p.data_compression_desc,
a.type_desc, p.[rows]
ORDER BY buffer_count DESC
Run Code Online (Sandbox Code Playgroud)
(Glenn Berry 的 DMV 查询的修改版本)。
要查看您允许 SQL Server 用于缓冲池(包括所有页面分配)和 CLR 分配的内容,您可以运行以下查询:
SELECT *
FROM sys.configurations
WHERE name = N'max server memory (MB)';
Run Code Online (Sandbox Code Playgroud)
或者
sp_configure N'show advanced options',1;
RECONFIGURE WITH OVERRIDE;
GO
sp_configure N'max server memory (MB)';
GO
Run Code Online (Sandbox Code Playgroud)
其中的一个config_value
(2147483647) 意味着您允许 SQL Server 使用它可以获得的一切。这可能会导致操作系统资源匮乏,进而开始收回内存并交换到页面文件 - 这是一个令人讨厌的场景。Glenn Berry(再次)有一个很好的建议,可以为最大服务器内存选择适当的设置(尽管它适用于 2008 年,但我没有找到适用于 >= 2012 年的良好指导)。
此外,由于您已经注意到您正在 SQL Server 2014 中进行测试,因此还有可能将缓冲池扩展到磁盘(仅当您连接了 SSD 存储时)。
当您运行查询时,SQL 需要将数据缓存在内存中。那是 9.3 Gigs 或其他。但是当您运行查询时,如果查询需要它,SQL 将在内存中创建哈希表以帮助连接,或创建您正在执行的任何计算等。这一切都发生在内存中。
SQL Server 非常擅长确定要使用多少内存。它不会无缘无故地消耗内存。如果它正在使用内存,那么它使用它是有原因的。
归档时间: |
|
查看次数: |
1103 次 |
最近记录: |