SQL 服务器:是否有更好的方法使用 where 子句编写此逻辑以提高性能

SQL Server : is there a better way to write this logic using a where clause to improve performance

我还是个写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

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

谁能帮帮我?

这是您的查询:

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 中使用的所有列都在索引中。也就是说索引可以满足查询,不需要引用数据页。

我会进行这两项更改以优化此查询:

  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。因此,很难根据您提供的信息(没有架构和解释计划)说 table 将是第一个。 因此,您也可以尝试添加这两个选项,一次添加一个,看看哪个效果更好: 选项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`);