这个简单的SQL查询可以优化吗?

ibi*_*iza 7 sql sql-server

我有以下查询:

SELECT COUNT(*) 
FROM Address adr INNER JOIN 
     Audit a on adr.UniqueId = a.UniqueId
Run Code Online (Sandbox Code Playgroud)
  • 在数据库上(130万个地址,超过400万次审计)
  • 两个UniqueId列都是群集主键

查询需要很长时间才能完成.我觉得愚蠢,但有没有办法优化它?我想计算所有具有基础可审计的地址条目.

编辑:非常感谢您的所有输入,这里有一些更多的细节:

  • 查询将不会经常运行(它仅用于验证),但是感谢索引的视图提示,我将肯定地添加到我的知识中.
  • 所有地址都有一对一的审核.并非所有审核都是地址.
  • 查询需要1分钟以上才能完成.我发现这个太长了,不需要简单计算.

Amy*_*y B 11

由于您有两组数据,按相同的值排序..您是否尝试过合并连接而不是嵌套循环连接?

SET STATISTICS IO ON
SET STATISTICS TIME ON

SELECT COUNT(*)  
FROM Address adr INNER JOIN  
     Auditable a on adr.UniqueId = a.UniqueId 
OPTION (LOOP JOIN)

SELECT COUNT(*)  
FROM Address adr INNER JOIN  
     Auditable a on adr.UniqueId = a.UniqueId 
OPTION (MERGE JOIN)

SELECT COUNT(*)  
FROM Address adr INNER JOIN  
     Auditable a on adr.UniqueId = a.UniqueId 
OPTION (HASH JOIN)
Run Code Online (Sandbox Code Playgroud)

编辑:

这些解释是概念性的.SQL Server可能比我的示例显示更复杂的操作.这种概念性理解与SET STATISTICS命令对时间和逻辑IO的测量以及查询执行计划的检查相匹配,构成了我的查询优化技术(长达四年)的基础.愿它和你一样为你服务.

建立

  • 获得5副牌.
  • 取1个牌组并生成父数据集.
  • 取其他4个套牌并生成子数据集.
  • 按卡值订购每个数据集.
  • 设m是父数据集中的卡数.
  • 设n是子数据集中的卡数.

NestedLoop

  • 从父数据集的顶部取出一张卡片.
  • 在子数据集内搜索(使用二分搜索)第一次出现匹配.
  • 从第一个匹配中查找子数据集,直到找到不匹配.你现在找到了所有的比赛.
  • 对父数据集中的每张卡重复此操作.

嵌套循环算法迭代父数据集,然后为每个父数据集搜索子数据集一次,使其成本为:m*log(n)

合并

  • 从父数据集的顶部取出一张卡片.
  • 从儿童数据集的顶部取出一张卡片.
  • 如果牌匹配,从每个牌组的顶部拉牌,直到每个牌都找不到.在父匹配和子匹配之间生成每个匹配对.
  • 如果卡不匹配,请在父卡和子卡之间找到较小的卡,并从该数据集的顶部取出卡.

合并连接算法迭代父数据集一次,子数据集迭代一次,使其成本为:m + n.它依赖于订购的数据.如果您要求对未订购的数据进行合并连接,则需要进行订购操作!这使得成本为(m*log(m))+(n*log(n))+ m + n.在某些情况下,甚至可能比嵌套循环更好.

哈希

  • 拿一张牌桌.
  • 从父数据集中取出每张卡并将其放在可以找到它的卡片表上(不必与卡片值有任何关系,只需要方便您).
  • 从子数据集中取出每张卡片,在纸板表上找到其匹配的父卡片并生成匹配的对.

散列连接算法迭代父数据集一次,子数据集迭代一次,使其成本为:m + n.它依赖于拥有足够大的卡表来保存父数据集的全部内容.


KM.*_*KM. 6

如果经常运行此查询并且需要超快,请创建它的物化索引视图.INSERT/UPDATE/DELETE会有轻微的开销,但这个查询只是即时的.可以预先计算聚合并将其存储在索引中,以最小化查询执行期间的昂贵计算.

使用SQL Server 2005索引视图提高性能