mel*_*okb 2 performance sql-server optimization condition azure-sql-database
我一直在努力理解如何处理在这种情况下经常出现的特定类型的性能问题:当您想在查询中应用多个过滤器,但您知道第一个过滤器将返回一个非常小的数字时来自一个非常大的表的行。
例如,我们有一个包含 10M+ 行的 3rd-party 异构表,其中的列根据TYPEID. 这是一个示例查询:
SELECT ID, NAME, INT109 FROM DATA WHERE TYPEID = 8301514 AND INT109 = 1
Run Code Online (Sandbox Code Playgroud)
在此查询中,两个过滤器没有覆盖索引,但在 'TYPEID' 列上有一个索引。令人困惑的是,即使表中的 10M 中只有大约 500 行TYPEID = 8301514,但此查询有时需要很多秒才能运行。
如果我只是INT109 = 1在最后删除过滤器,查询几乎立即运行:
SELECT ID, NAME, INT109 FROM DATA WHERE TYPEID = 8301514
Run Code Online (Sandbox Code Playgroud)
对我来说,使用较少的过滤器会使查询运行得更快是没有意义的。此外,行为似乎不一致 - 如果第一个查询已经运行多次,它也可以运行得非常快,就像正在缓存某些东西一样。很难做可靠的实验(这是在 SQL Azure 中)。这是正常行为吗?这是否是由错误的执行计划(即使我没有使用参数)或过时的统计数据引起的?
这里可能发生的事情是,在某个时候,您运行第一个查询的值超过 500 行 - 如此之多以至于它认为扫描 10M 行比进行数十万次查找要好名称和 INT109 列。然后该计划被缓存,并在您提供不同的价值时重用,该价值将从不同的计划中受益。SQL 假设避免重新编译比评估您可以提供的每个不同值更好。
当您编写不同的查询时,它会对其进行新鲜评估,并给出最佳计划,尽管这对于不同的值可能并不理想。
解决这个问题的最好方法是在 上建立一个索引(TYPEID, INT109) INCLUDE (ID, Name),这样就不需要查找,并且无论 TYPEID 周围的统计数据如何,计划都会进行搜索。另外,即使您省略 INT109,该索引也很有用。
| 归档时间: |
|
| 查看次数: |
123 次 |
| 最近记录: |