【问题标题】:SQL server optimization IssueSQL 服务器优化问题
【发布时间】:2016-12-07 15:49:34
【问题描述】:

我有以下查询

SELECT DISTINCT ColA,ColB AS S 
   from TableA  
   where ColA <> 0        
   AND CONCAT(ColA,ColB) NOT IN (
                                   SELECT DISTINCT CONCAT(ColA,ColB) from TableB
                                   WHERE ColB <> 0
                                )

TableA 有大约200000 条记录和

TableB 有大约50000 记录

当我运行这个查询时,它花费了大约 2 分钟的时间。

如何优化此查询以减少执行时间?

我应该如何优化这个查询?

【问题讨论】:

  • 请将执行计划发布为 xml,包含一些示例数据的表模式
  • ColA &lt;&gt; 0 AND AND CONCAT 中有两个 AND
  • cols 是数字吗?你确定将它们连接起来吗? select concat (a,b) from (select 11 as a, 2 as b union all select 1, 12) t where concat (a,b) ='112'

标签: sql sql-server-2012 query-optimization


【解决方案1】:

试试这个....

SELECT DISTINCT A.ColA, A.ColB AS S 
from TableA  A
where A.ColA <> 0 
AND NOT EXISTS (SELECT 1
                from TableB B
                WHERE B.ColB <> 0
                AND A.ColA= B.ColA
                AND A.ColB = B.ColB)

注意

我对您的表架构或索引了解不多,但我肯定知道表达式 CONCAT(ColA,ColB) 不是 Sargable。以不同的方式编写相同的查询,如果在列ColAColB 上有索引,它会更快。

【讨论】:

  • 理论上,您的查询可能会带来不正确的结果。在您的情况下,CONCAT(ColA, ColB) 将等于 CONCAT(ColB, ColA),不是吗?
【解决方案2】:

CONCAT 将排除对两个表中列的任何索引搜索。

如果您查询的主要目的是查找 TableA 中而不是 TableB 中的所有 ColA、ColB 组合,您可以尝试这样的操作。

SELECT DISTINCT ColA,ColB AS S 
FROM TableA  
WHERE ColA <> 0
AND NOT EXISTS(
    SELECT TOP 1 * FROM TableB
    WHERE TableB.ColA = TableA.ColA
    AND TableB.ColB = TableA.ColB 
    AND TableB.ColB <> 0
   )

注意:这应该会产生比您当前的查询更好的执行计划,但是如果没有您的实际执行计划和现有的表结构和索引,很难评论

【讨论】:

    【解决方案3】:

    使用set operation:

    SELECT ColA, ColB FROM TableA WHERE ColA <> 0
    EXCEPT
    SELECT ColA, ColB FROM TableB WHERE ColB <> 0
    

    不需要DISTINCT,因为EXCEPT 无论如何都要这样做。

    【讨论】:

      【解决方案4】:

      你可以试试这个查询

      SELECT DISTINCT ColA,ColB AS S
      FROM TableA LEFT OUTER JOIN TableB 
          ON TableA.ColA = TableB.ColA
            and TableA.ColB = TableB.ColB
      WHERE TableA.ColA <> 0
          and TableB.ColB <> 0
          and TableB.ColB is null
      

      【讨论】:

        【解决方案5】:

        正如一些发帖者所指出的,您需要使用 CONCAT 而不是单独查询 ColA 和 ColB 来获取正确的数据。

        如果这是一个足够重要的查询,值得拥有自己的索引,或者 CONCAT(ColA, ColB) 是常用的数据。您可以考虑为 CONCAT(ColA, ColB) 创建一个计算列,并在该计算列上创建一个索引。

            SELECT DISTINCT 
            A.ColA, A.ColB
            FROM TableA A 
            LEFT JOIN TableB B 
            ON B.CONCAT(ColA,ColB) = A.CONCAT(ColA,ColB)
            WHERE A.ColA <> 0
            and B.ColB <> 0
            and B.ColB is null
        

        我也有幸使用 CTE 进行过滤,然后最后进行任何计算,以充分利用当前表上的索引。

            WITH FilteredA as (
            select ColA, ColB
            from tableA 
            WHERE ColA <> 0 ), 
        
            FilteredB as (
            select ColA, ColB
            from tableB 
            WHERE ColB <> 0 ) 
        
            SELECT DISTINCT FilteredA.*
            from FilteredA 
            LEFT JOIN FilteredB ON FilteredA.ColA = FilteredB.ColB
            AND FilteredA.ColB = FilteredB.ColB
            WHERE FilteredA.CONCAT(ColA,ColB) = FilteredB.CONCAT(ColA,ColB)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-02-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-03
          • 1970-01-01
          • 2023-03-29
          • 2010-12-04
          相关资源
          最近更新 更多