为啥在视图中使用此查询会变慢?

Posted

技术标签:

【中文标题】为啥在视图中使用此查询会变慢?【英文标题】:Why is this query slower when used in a view?为什么在视图中使用此查询会变慢? 【发布时间】:2013-10-11 15:13:14 【问题描述】:

我有这个问题:

SELECT * FROM
(
SELECT LASTNAME,NAME,STREET,PHONE,ID_CARD 
FROM PHONES1..TVPHONES  
UNION ALL

SELECT LASTNAME,NAME,STREET,PHONE,ID_CARD 
FROM PHONES2..TVPHONES 
UNION ALL

SELECT LASTNAME,NAME,STREET,PHONE,ID_CARD 
FROM PHONES3..TVPHONES
) q 
WHERE ID_CARD = 'B5XXXXXXX'

此查询需要 0.03 秒才能完成,但如果我将其转换为视图并执行相同的搜索:

ALTER VIEW [dbo].[BTPHONES]  
AS

 SELECT * FROM
    (
    SELECT LASTNAME,NAME,STREET,PHONE,ID_CARD 
    FROM PHONES1..TVPHONES  
    UNION ALL

    SELECT LASTNAME,NAME,STREET,PHONE,ID_CARD 
    FROM PHONES2..TVPHONES 
    UNION ALL

    SELECT LASTNAME,NAME,STREET,PHONE,ID_CARD 
    FROM PHONES3..TVPHONES
    ) q 

GO

-- ------------------------

SELECT TOP 1 * FROM dbo.BTPHONES
WHERE ID_CARD = 'B5XXXXXXX'

大约需要 3 分钟!为什么需要这么长时间?

计划01:

计划02:

【问题讨论】:

你对比过实际的执行计划吗? 我运行了 CTRL + L。在第一种情况下,大部分查询的成本为 0%。相比之下,在第二种情况下,成本从 40% 到 60% 不等 @csotelo 您应该将其发布为答案 另外,查询是不等价的 - 顶部只返回所有结果,底部必须选择任意 TOP 1。为什么使用没有 ORDER BY 的 TOP 1? 添加TOP 1 可以大大改变计划(鼓励嵌套循环等非阻塞运算符) 【参考方案1】:

第二种情况等价于:

SELECT TOP 1 * FROM (
  SELECT * FROM
  (
    SELECT LASTNAME,NAME,STREET,PHONE,ID_CARD 
    FROM PHONES1..TVPHONES  
    UNION ALL

    SELECT LASTNAME,NAME,STREET,PHONE,ID_CARD 
    FROM PHONES2..TVPHONES 
    UNION ALL

    SELECT LASTNAME,NAME,STREET,PHONE,ID_CARD 
    FROM PHONES3..TVPHONES
  ) q
)
WHERE ID_CARD = 'B5XXXXXXX'

优化器可能没有意识到它可以将 where 子句应用于每个内部选择。相反,它会创建整个表的并集,然后对结果进行全面扫描以应用 where 子句。

【讨论】:

以上是关于为啥在视图中使用此查询会变慢?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 MySQL 查询在使用 LIMIT 和 Order BY 时会变慢?

当我在 viewcontroller 上使用 3 视图时,目标 c 会变慢

如果在多个系统调用中完成,为啥 TCP 套接字会变慢?

为啥我的程序在使用 makefile 编译时会变慢?

使用 Circe Json 为啥隐式解析在运行时会变慢

为啥我们的 React Native 应用在 Android 手机上使用时会变慢?