SQL Server中Geometry.STContains查询首次运行缓慢,如何让表常驻内存?
让SQL Server地理表常驻内存的直接实现方案
针对你遇到的间隔一两天首次查询慢、推测表被内存卸载的问题,以下是几种更直接的实现方式:
1. 改用内存优化表(In-Memory OLTP)
这是最彻底的解决方案,把TractGeometry和tract这类高频访问表改成内存优化表,数据会直接常驻内存,完全不会被系统换出。
- 注意:要确保表结构兼容内存优化(比如避开TEXT/NTEXT等不支持的类型)
- 创建示例:
CREATE TABLE [dbo].[Tract_InMemory] ( Id INT PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 1000000), -- 原表其他列照抄 ) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA); CREATE TABLE [dbo].[TractGeometry_InMemory] ( TractId INT PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 1000000), [geometry] GEOMETRY, -- 原表其他列照抄 ) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA);
之后把原表数据导入到这些内存表,查询直接指向新表即可。
2. 高效预加载数据到缓存
如果不想改表结构,就用更轻量的方式替代普通调度查询,强制把表数据加载到缓存:
- 写一个轻量查询(只查必要列,避免全表数据占用过多内存),比如:
-- 加载tract表核心数据到缓存 SELECT Id FROM [dbo].[tract] WITH (NOLOCK); -- 加载TractGeometry的地理数据和关联ID到缓存 SELECT TractId, [geometry].STAsBinary() FROM [dbo].[TractGeometry] WITH (NOLOCK);
- 把这个查询做成SQL Agent作业,设置每天空闲时段执行一次,或者系统重启后自动触发。用
NOLOCK是为了避免预加载时锁表影响业务。
3. 调整SQL Server内存配置
确保SQL Server有足够内存预留,避免因为内存压力把缓存的表数据踢出去:
- 可以通过SSMS操作:右键数据库实例 → 属性 → 内存,设置「最大服务器内存(MB)」为服务器总内存的80%左右(留够内存给操作系统)
- 也用T-SQL设置:
sp_configure 'show advanced options', 1; RECONFIGURE; sp_configure 'max server memory (MB)', 32768; -- 数值根据你的服务器内存调整 RECONFIGURE;
4. 创建覆盖索引
给你的查询做一个覆盖索引,既能加速查询,还能让索引(连带必要数据)因为高使用率更难被缓存移除:
CREATE NONCLUSTERED INDEX IX_TractGeometry_Geometry ON [dbo].[TractGeometry] ([geometry]) INCLUDE (TractId);
这个索引包含了查询需要的geometry列和关联用的TractId,查询时直接走索引,不用回表,索引数据会长期驻留缓存。
内容的提问来源于stack exchange,提问作者JimmyV
相关产品推荐
相关产品推荐

