У меня есть эта база данных:
Tab1 --- 1: n --- > tab2 (parent- > id) (max1: 4) - сложная часть
Tab1 --- 1: n --- > tab3 (parent- > id) - простое соединение
ID
имя
версия
..и т.д.
ID
родитель
тип
цена
..и т.д.
ID
родитель
тип
данные
Я хотел бы выбрать полный набор информации из этих трех связанных таблиц, но мне нужно использовать множество переменных условий, поэтому мне нужно придумать лучшее решение, насколько это возможно.
Я использую этот запрос:
SELECT tab1.id, CONCAT(tab1.name,' ',tab1.version) AS nv, ndvar.price, tab3.data,
ndvar.v1
[more columns]
FROM tab1 INNER JOIN (
SELECT parent,
type,
GROUP_CONCAT(type SEPARATOR '') + '' AS v1,
MIN(price) AS price
[more columns]
FROM tab2
WHERE show = 1
[more condition]
GROUP BY parent
HAVING type IN (2,3) [1-3 parameters]
)
AS ndvar
ON tab1.id = ndvar.parent
LEFT JOIN content
ON tab1.id = tab3.parent AND tab3.type = 0
WHERE name LIKE '%xyz%'
[more conditions]
ORDER BY nv
Я попытался сделать так же просто, как мог.
Мои вопросы: 1) Как оптимизировать этот запрос, чтобы как можно быстрее 2) Какие столбцы используются в качестве индексов? На данный момент это только столбец "id".
Столбец 'type' в tab2 содержит значения 0-3, и для каждого идентификатора есть только строка с этим типом, поэтому есть coul по индексу, но я не знаю, будет ли он делать какие-либо улучшения в моем запросе.
Спасибо заранее.
Это запрос, используемый во время поиска в онлайн-каталоге, в течение месяца будет всего несколько вложений или обновлений, но многие поисковые запросы каждый день. Tab1 будет содержать сотни записей, tab2 вокруг tab1 * 4 записей и tab3 вокруг tab1 * 15 записей. Существует много условий поиска, включающих в основном tab1 (1-15 параметров) и tab2 для 3 параметров. Все параметры - это числа (double), кроме имени и версии, которые являются именами - varchar (25) и версией - varchar (20).
Запрос будет выполнен на mysql 5.0.70, движок db MyISAM
По всем статистическим данным, поиск по диапазону tab2.price и tab2.type является наиболее распространенным, и поиск других диапазонов чисел более распространен, чем поиск по tab1.name или tab1.version.
Я с удовольствием заполню любую другую информацию, которую кто-то спросит.
Кстати: извините за мою бедную грамматику, английский не мой родной язык:)
Я мог бы неверно истолковать всю концепцию "HAVING". В v1 мне нужно сохранить весь набор значений из строк tab2 для каждого родителя из tab1, но мне нужно отфильтровать их с помощью tab2.type.. как это сделать?
Этот тип агрегации возвращает именно то, что мне нужно, НО - я знаю его страшное решение, кто-то знает, как его улучшить?
GROUP BY parent
HAVING v1 LIKE '%0%
Tab2.type и tab1.id, tab2.parent и tab3.parent, вероятно, являются наиболее важными строками для индексов, если они идентифицируют очень конкретные строки.
Что касается индексов, то другие, которые могут помочь, - tab2.price, tab3.type.
Как правило, чем больше строк условие должно исключать из результатов, тем хуже нужен индекс.
"WHERE name LIKE '% stuff%', вероятно, является одним из условий WORST для использования в мире (хотя и один из наиболее распространенных), потому что обычные индексы ничего не делают. Если этот тест устраняет много строк из результат (это значит, что он тестирует много строк и несколько передает условие), тогда вы должны использовать полнотекстовый индекс.
Суб-выбор после внутреннего соединения может быть высокопроизводительным зависанием, так как он должен создавать результирующий набор независимо.