【问题标题】:Sql Server query taking too much timeSql Server 查询耗时过长
【发布时间】:2018-11-03 01:03:32
【问题描述】:

以下查询执行需要 45 秒。如何提高速度?

SELECT
    u.i_UserID, 
    u.vch_LoginName,         
    ea.vch_EmailAddress, 
    u.vch_DisplayName,
    'Current' As 'vch_RecordStatus'
FROM
    tblUser u 
    LEFT JOIN [User].dbo.tblEmailAddress ea 
       ON u.i_EmailAddressID = ea.i_EmailAddressID
WHERE
    IsNull(u.vch_LoginName, '') Like '%'
    AND u.vch_DisplayName LIKE 'kala' -- 14 secs

UNION ALL   -- 29 secs

SELECT
    DISTINCT l.i_UserID
    ,l.vch_OldLoginName as vch_LoginName
    ,l.vch_OldEmailAddress as vch_EmailAddress
    ,u.vch_DisplayName as vch_DisplayName,
    'Old' As 'vch_RecordStatus'
FROM tblUserStatusLog l
INNER JOIN tblUser u on u.i_UserID = l.i_UserID
WHERE 
    l.vch_OldLoginName  Like '%'
    AND u.vch_DisplayName LIKE 'kala' -- 28 secs
ORDER BY
    u.vch_LoginName

【问题讨论】:

  • 为了改善您的问题,请告诉我们更多有关表结构、行数、索引、机器等的信息...
  • 您很可能需要改进索引。如果您需要更多帮助,请在您的问题中包括创建表和索引语句、查询计划和统计 io 输出。
  • IsNull(u.vch_LoginName, '') Like '%' 和l.vch_OldLoginName Like '%' 没有任何意义,这个有什么用?
  • 需要显示查询计划。

标签: sql-server


【解决方案1】:

首先,为什么要使用LIKE 来比较字符串? LIKE 用于比较部分字符串,您应该使用= 运算符来搜索精确匹配。

我也不明白两个 where 子句的第一个条件,您是否要检查它们不是空字符串而不是 null 吗?最好使用IS NOT NULL 和<> 运算符:

SELECT
    u.i_UserID, 
    u.vch_LoginName,        
    ea.vch_EmailAddress, 
    u.vch_DisplayName,
    'Current' As 'vch_RecordStatus'
FROM
    tblUser u 
    LEFT JOIN [User].dbo.tblEmailAddress ea ON u.i_EmailAddressID = ea.i_EmailAddressID
WHERE
    u.vch_LoginName is not null and u.vch_loginname <> ''
    AND u.vch_DisplayName = 'kala' 
    UNION ALL   

    SELECT
        DISTINCT l.i_UserID
        ,l.vch_OldLoginName as vch_LoginName
        ,l.vch_OldEmailAddress as vch_EmailAddress
        ,u.vch_DisplayName as vch_DisplayName,
        'Old' As 'vch_RecordStatus'
    FROM tblUserStatusLog l
    INNER JOIN tblUser u on u.i_UserID = l.i_UserID
    WHERE 
        l.vch_OldLoginName <> ''
        AND u.vch_DisplayName = 'kala' 
        ORDER BY
    u.vch_LoginName 

除此之外,我假设您可以通过向表中添加适当的索引来显着提高性能,但我们需要您的表结构来查看已经存在的内容。

但是您应该在前两个表上的i_EmailAddressID 上具有索引,在第二个表上具有i_userId 上的索引,并且vch_OldLoginName,vch_displayName 上的索引也可能会改进运行。

【讨论】:

  • 嗨,我需要 u.vch_LoginName 为空值...那是我提出的条件。还有其他方法可以获取空值
  • 对不起,我不明白你到底想做什么,我发布的查询不起作用? @BabuAtcha
  • 嗨 Sagi,为什么只显示 50 条记录需要 25 秒...请您更正查询...SELECT DISTINCT l.i_UserID ,l.vch_OldLoginName as vch_LoginName ,l.vch_OldEmailAddress as vch_EmailAddress , u.vch_DisplayName as vch_DisplayName, 'Old' As 'vch_RecordStatus' FROM tblUserStatusLog l INNER JOIN tblUser u on u.i_UserID = l.i_UserID WHERE u.vch_DisplayName LIKE 'kala'
  • 按照我的指示,添加索引并使用我的查询,一切都会好起来的。
【解决方案2】:

你想看看索引。当您在打开实际执行计划的情况下运行此查询时,您是否得到任何缺失的查询提示?确保所有索引都针对此查询进行了优化,您将获得更好的性能。

您包含 tblEmailAddress 的完整路径,它是否存储在另一个名为“用户”的数据库中?如果是这样,您将希望减少从链接服务器中提取的数据量。同样,索引应该可以帮助您。

您也不希望在 where 子句中进行计算。查看查询的 SARGability。 https://en.wikipedia.org/wiki/Sargable 这会告诉你为什么你的 LIKE 语句也是一个坏主意。

【讨论】:

  • 嗨 Benner,为什么只显示 50 条记录需要 25 秒...您能否更正查询..SELECT DISTINCT l.i_UserID ,l.vch_OldLoginName as vch_LoginName ,l.vch_OldEmailAddress as vch_EmailAddress , u.vch_DisplayName as vch_DisplayName, 'Old' As 'vch_RecordStatus' FROM tblUserStatusLog l INNER JOIN tblUser u on u.i_UserID = l.i_UserID WHERE u.vch_DisplayName LIKE 'kala'
  • SELECT DISTINCT l.i_UserID ,l.vch_OldLoginName as vch_LoginName ,l.vch_OldEmailAddress as vch_EmailAddress ,u.vch_DisplayName as vch_DisplayName, 'Old' As 'vch_RecordStatus' FROM tblUserStatusLog l INNER JOIN tblUser u on u.i_User = l.i_UserID WHERE u.vch_DisplayName LIKE 'kala'
  • 如果您需要添加代码,请编辑问题而不是将其发布在 cmets 中。唯一明显的是你的 LIKE 语句应该是 =。之后,您将不得不查看实际的执行计划以了解发生了什么(并检查缺少的查询提示)
猜你喜欢
  • 1970-01-01
  • 2013-07-24
  • 1970-01-01
  • 2015-08-19
  • 2020-11-09
  • 1970-01-01
  • 2019-08-02
相关资源
最近更新 更多