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
中使用的所有列都在索引中。也就是说索引可以满足查询,不需要引用数据页。
我会进行这两项更改以优化此查询:
- 首先,我会将查询分成两部分,结合 UNION(如果您不关心删除重复项,最好使用 UNION ALL),但也可以使用 UNION DISTINCT。这种拆分将允许 MySQL 更好地索引 WHERE 过滤器,因为它在使用 OR 条件时无法在索引中正确搜索。
- 添加适当的索引。
那么让我们看看优化后的查询:
(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`);
我还是个写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
中使用的所有列都在索引中。也就是说索引可以满足查询,不需要引用数据页。
我会进行这两项更改以优化此查询:
- 首先,我会将查询分成两部分,结合 UNION(如果您不关心删除重复项,最好使用 UNION ALL),但也可以使用 UNION DISTINCT。这种拆分将允许 MySQL 更好地索引 WHERE 过滤器,因为它在使用 OR 条件时无法在索引中正确搜索。
- 添加适当的索引。
那么让我们看看优化后的查询:
(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`);