Я все еще новичок в написании 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
Примечание: мне не следует использовать первичные ключи для фильтрации этих результатов.
Может кто-нибудь мне помочь?
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') 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, поскольку он не может правильно выполнять поиск в индексах при использовании условия ИЛИ.
- Добавьте правильные индексы.
Итак, давайте посмотрим на оптимизированный запрос:
(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`);
Вариант Б:
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
Язык структурированных запросов (SQL) - это язык запросов к базам данных. Вопросы должны включать примеры кода, структуру таблицы, примеры данных и тег для используемой реализации СУБД (например, MySQL, PostgreSQL, Oracle, MS SQL Server, IBM DB2 и т. Д.). Если ваш вопрос относится исключительно к конкретной СУБД (использует определенные расширения / функции), используйте вместо этого тег этой СУБД. Ответы на вопросы, помеченные SQL, должны использовать стандарт ISO / IEC SQL.