Spa*_*152 2 sql-server clustered-index index-tuning
我有一个存储时间序列数据的表,大约有 800 万行。表结构如下:
时间戳| 组件 ID | 参数1 | 参数2 | 参数3
我在Timestamp和ComponentID列上有一个聚集索引。(这也是我的主键)
我试图运行的查询是:-
SELECT * FROM table
WHERE Timestamp BETWEEN '2020-01-01'
AND '2020-01-02'
AND ComponentId = 5
Run Code Online (Sandbox Code Playgroud)
当我运行此查询时,似乎正在发生 RID 查找。我读过,只有当索引没有覆盖所有内容时才会发生这种情况,但由于我有一个聚集索引,我认为它本身应该覆盖所有内容并阻止查找。如何防止这种查找发生?
RID 查找发生在SQL Server 中的堆数据结构上(而不是B 树)。当使用非覆盖非聚集索引来获取数据并且需要查找其丢失的剩余字段时,就会发生这种情况。当表上没有聚集索引时,表数据存储在堆中(因为聚集索引定义了记录通常排序到B 树中的顺序)。
如果您的表有聚集索引,并且此查询想要使用当前使用的相同非聚集索引,那么您会在执行计划中看到键查找操作。
如果您在表上为这两个字段创建了聚集索引Timestamp
,ComponenentID
那么这将覆盖您的查询,并且您应该看到执行计划中使用的聚集索引,这将消除任何类型的额外查找操作。
关于评论中的第二个问题,根据您最近的评论更新,听起来您看到的运行时差异是由于第一次运行将数据从磁盘拉入内存(这通常是该过程中最瓶颈的部分) ,从硬件角度来看),第二次运行利用内存中的现有数据。
根据您的表和页面大小的大小,这通常不应该太令人担忧(根据我看到您的查询从其执行计划返回的行数)。查询的所有后续运行(当数据仍在内存中时)都将具有最佳性能。
如果从磁盘上提取数据的初始运行出现问题,那么您可以研究压缩或分析是否可以将磁盘升级到更快的速度(不确定您当前是否仍在机械硬盘驱动器上,并且可以切换SSD或更好的是NVMe )。
我还将添加最后一条注释,该注释是真实且相关的,但不是根本问题本身,即您的查询对导致ComponentId
读取更多数据的结果进行了额外的过滤。如果您比较两个查询之间的逻辑读取总数,这一点在IO 统计屏幕截图中会很明显。一个查询过滤并导致 396 个逻辑读取,而另一个查询过滤仅导致 90 个逻辑读取。逻辑读取是从内存读取的8 KB 页数。物理读取是从磁盘读取的8 KB 页数。这并不是一个巨大的差异,但会导致在第一次运行时运行第一个查询与第二个查询之间的时间存在微小差异。当数据已经从磁盘存储在内存中时,这将成为后续运行两个查询的一个有争议的问题(如我之前几段所述)。Timestamp
ComponentId
Timestamp
归档时间: |
|
查看次数: |
4962 次 |
最近记录: |