【问题标题】:SQL Server : is there a better way to write this logic using a where clause to improve performanceSQL Server:有没有更好的方法来编写这个逻辑,使用 where 子句来提高性能
【发布时间】:2018-01-03 00:59:50
【问题描述】:

我还是一个写SQL查询的新手,不知道有没有更好的方法在下面的查询中写where子句来提高过滤结果的性能?

查询:

SELECT    
    B.col1, A.col1, A.col2   
FROM 
    tblB B  
INNER JOIN 
    tblA A ON B.ID = A.ID   
WHERE   
    ((B.T_No NOT LIKE '123%' AND b.StartDate < '2001-01-01') 
     OR
     (B.T_No NOT LIKE '234%' AND b.StartDate < '2005-01-01')
    )
    AND B.BName = 'sth'
    AND B.c_Val = 33

注意:我不应该使用主键来过滤这些结果。

谁能帮帮我?

【问题讨论】:

  • 拥有最新的统计数据和适当的索引,就可搜索的问题而言,它看起来还不错

标签: sql sql-server performance where-clause


【解决方案1】:

这是您的查询:

SELECT B.col1, A.col1, A.col2   
FROM tblB B INNER JOIN
     tblA A
     ON B.ID = A.ID   
WHERE ((B.T_No NOT LIKE '123%' AND b.StartDate < '2001-01-01') OR
       (B.T_No NOT LIKE '234%' AND b.StartDate < '2005-01-01')
      ) AND
      B.BName = 'sth' AND
      B.c_Val = 33;

where 子句不会对性能产生很大影响。有什么不同的是索引。为此,我建议tblB(BName, c_Val, StartDate, t_no, id, col)。您还需要tblA(id) 上的索引(如果尚未声明为唯一或主键)。

这是查询的覆盖索引,这意味着tblB 中使用的所有列都在索引中。这意味着索引可以满足查询,无需参考数据页。

【讨论】:

  • StartDate 应该在索引中的t_no 之前
  • 查看 tblB 索引时,我认为 MySQL 不能在 StartDate 之后继续使用索引搜索到 t_no,因为它们都是范围搜索?另外,为什么在 tblB 的索引中的范围列之后将 id 添加到索引中? WDYT?
【解决方案2】:

我会通过这两个更改来优化此查询:

  1. 首先,我将查询分为两部分,结合一个 UNION(如果您不关心删除重复项,最好使用 UNION ALL),但也可以使用 UNION DISTINCT。这种拆分将允许 MySQL 更好地索引 WHERE 过滤器,因为它在使用 OR 条件时无法正确搜索索引。
  2. 添加适当的索引。

那么我们来看看优化后的查询:

(SELECT 
    B.col1, A.col1, A.col2
FROM
    tblB B
        INNER JOIN
    tblA A ON B.ID = A.ID
WHERE
    ((B.T_No NOT LIKE '123%'
        AND B.StartDate < '2001-01-01'))
        AND B.BName = 'sth'
        AND B.c_Val = 33) UNION DISTINCT (SELECT 
    B.col1, A.col1, A.col2
FROM
    tblB B
        INNER JOIN
    tblA A ON B.ID = A.ID
WHERE
    ((B.T_No NOT LIKE '234%'
        AND B.StartDate < '2005-01-01'))
        AND B.BName = 'sth'
        AND B.c_Val = 33)

关于索引:MySQL 有很多因素来决定是从 tblA 还是 tblA 开始加入。因此,很难用您提供的信息(没有模式和解释计划)说哪个表将是第一个。 因此,您也可以尝试一次添加这两个选项,看看哪个效果更好: 选项 A:

ALTER TABLE `tblA` ADD INDEX `tblA_index_1` (`col1`, `col2`);
ALTER TABLE `tblB` ADD INDEX `tblB_index_1` (`BName`, `c_Val`, `ID`, `StartDate`, `col1`);

选项 B:

ALTER TABLE `tblA` ADD INDEX `tblA_index_1` (`ID`, `col1`, `col2`);
ALTER TABLE `tblB` ADD INDEX `tblB_index_1` (`BName`, `c_Val`, `StartDate`, `col1`);

【讨论】:

  • OR 通常是 SQL Server 中的性能杀手。我肯定会试试这个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-15
  • 1970-01-01
  • 1970-01-01
  • 2022-11-01
  • 1970-01-01
相关资源
最近更新 更多