我的数据库中有一个表格,我将其编入索引为三列:PropertyId
,ConceptId
和Sequence
。这个特殊的表中有大约90,000行,它在这三个属性上编入索引。
现在,当我运行此查询时,所需的总时间大于2分钟:
SELECT *
FROM MSC_NPV
ORDER BY PropertyId, ConceptId, Sequence
但是,如果我像这样对查询进行分页:
SELECT *
FROM MSC_NPV
ORDER BY PropertyId, ConceptId, Sequence
OFFSET x * 10000 ROWS
FETCH NEXT 10000 ROWS ONLY
所需的总时间(x从0到8)仅为20秒左右。
这对我来说似乎违反直觉,因为分页需要额外的操作,而不是更简单的查询,我们正在增加顺序网络调用所需的额外延迟,因为我根本没有并行化这个查询。而且,我知道这不是缓存问题,因为一个接一个地运行这些查询并不会对延迟产生太大影响。
所以,我的问题是:为什么一个比另一个快得多?
答案 0 :(得分:1)
这似乎违反直觉,因为分页需要额外的操作,而不仅仅是简单的查询
如果您有正确的索引,有时候分页查询的工作速度非常快......
例如,使用以下查询
-o
您可能阅读的最大行数仅为20000 ..下面是一个证明相同
的示例RunTimeCountersPerThread Thread =“0”ActualRows =“60”ActualRowsRead =“60”
但是使用OFFSET x * 10000 ROWS
FETCH NEXT 10000 ROWS ONLY
查询..您正在阅读所有行
答案 1 :(得分:0)
经过长时间搜索这里发生的事情后,我发现这种性能差异背后的原因(> 2分钟)是由于在Azure上托管数据库。由于Azure跨多个分区(即多台计算机)对您托管的任何表进行分区,因此运行如下查询:
SELECT *
FROM MSC_NPV
ORDER BY PropertyId, ConceptId, Sequence
运行速度会更慢,因为查询会在排序之前从所有分区中提取数据,这可能会导致同一个表中多个分区之间的多个查询。通过在索引属性上对查询进行分页,我正在查看特定分区并查询存储在那里的表,这就是为什么它的性能明显优于非分页查询。
为了证明这一点,我又跑了另一个问题:
SELECT *
FROM MSC_NPV
ORDER BY Narrative
OFFSET x * 10000 ROWS
FETCH NEXT 10000 ROWS ONLY
与第一个分页查询相比,此查询运行不正常,因为Narrative
不是主键,因此Azure不会使用它来构建分区键。因此,Narrative
上的排序需要与第一个查询相同的操作以及其他操作,因为必须事先获得整个表。