使用 UNION 子查询的查询需要很长时间

Ste*_*ott 5 sql t-sql sql-server azure-sql-database

我在某些依赖于子查询的查询上遇到了一个奇怪的问题。它们运行得快如闪电,直到我在子查询中使用 UNION 语句。然后他们就无休无止地跑,我10分钟后就给了。我现在描述的场景不是我一开始的场景,但我认为它消除了很多可能的问题,但却产生了同样的问题。因此,即使这是一个毫无意义的问题,请耐心等待!

\n\n

我有一张桌子:

\n\n
tblUser - 100,000 rows\ntblFavourites - 200,000 rows\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果我执行:

\n\n
SELECT COUNT(*) \nFROM tblFavourites \nWHERE userID NOT IN (SELECT uid FROM tblUser);  \n
Run Code Online (Sandbox Code Playgroud)\n\n

\xe2\x80\xa6 然后它运行不到一秒钟。但是,如果我修改它以使子查询具有 UNION,它将运行至少 10 分钟(在我放弃之前!)

\n\n
SELECT COUNT(*) \nFROM tblFavourites \nWHERE userID NOT IN (SELECT uid FROM tblUser UNION SELECT uid FROM tblUser);  \n
Run Code Online (Sandbox Code Playgroud)\n\n

这是毫无意义的改变,但它应该产生相同的结果,我不明白为什么它应该花更长的时间?

\n\n

将子查询放入视图中并调用它具有相同的效果。

\n\n

有什么想法吗?我正在使用 SQL Azure。

\n\n
\n\n

问题解决了。请参阅下面我的回答。

\n\n
\n

JNK*_*JNK 5

UNIONDISTINCT实际上是对组合数据集中的所有字段进行操作。它会过滤掉最终结果中的重复内容。

是否已Uid编入索引?如果不是,查询引擎可能需要很长时间:

  • 生成第一个结果集
  • 生成第二个结果集
  • 过滤掉哈希表中的所有重复项(即一半记录)

如果重复项不是问题(并且使用IN意味着它们不会),那么使用UNION ALL它可以消除昂贵的排序/过滤步骤。


Ste*_*ott 1

事实证明,问题是由于索引之一... tblFavourites 包含 tblUser 中主键 (uid) 的两个外键:

userId
otherUserId
Run Code Online (Sandbox Code Playgroud)

两列具有相同的定义和相同的索引,但我发现在原始查询中将 userId 替换为 otherUserId 解决了问题。

我跑:

ALTER INDEX ALL ON tblFavourites REBUILD
Run Code Online (Sandbox Code Playgroud)

...然后问题就消失了。现在查询几乎立即执行。

我不太了解 Sql Server/Azure 幕后发生的事情......但我只能想象它是损坏的索引或其他什么?我经常更新统计数据,但这没有效果。

谢谢!

- - 更新

以上并不完全正确。它确实解决了大约 20 分钟的问题,然后又恢复了。我已经与 Microsoft 支持人员联系了几天,问题似乎与 tempDB 有关。他们最终正在研究解决方案。