У нас есть веб-сайт с 250-миллиметровыми строками в одной таблице, а в другой, к которой мы присоединяемся, для большинства запросов чуть менее 15-миллиметровых строк.
Примерные структуры:
MasterTable (Id, UserId, Created, Updated...) -- 15MM Rows
DetailsTable (Id, MasterId, SomeColumn...) -- 250MM Rows
UserTable (Id, Role, Created, UserName...) -- 12K Rows
Нам регулярно приходится делать несколько запросов ко всем этим таблицам. Одним из них является сбор статистики для бесплатных пользователей (~ 10 тыс. Бесплатных пользователей).
Select Count(1) from DetailsTable dt
join MasterTable mt on mt.Id = dt.MasterId
join UserTable ut on ut.Id = mt.UserId
where ut.Role is null and mt.created between @date1 and @date2
Проблема в том, что этот запрос иногда выполняется слишком долго из-за того, что соединения происходят задолго до того, как.
В этом случае было бы разумнее использовать Wheres вместо объединений или , возможно where column in(...)
?
join
best-practices
Джереми Бойд
источник
источник
Ответы:
Для современных СУБД нет никакой разницы между «явным СОЕДИНЕНИЕМ» и «СОЕДИНЕНИЕМ В ГДЕ» (если все СОЕДИНЕНИЯ являются ВНУТРЕННИМИ) в отношении производительности и плана запросов.
Явный синтаксис JOIN более четкий и менее двусмысленный (см. Ссылки ниже)
Теперь JOIN-before-WHERE - это логическая обработка, а не фактическая обработка, и современные оптимизаторы достаточно умны, чтобы это реализовать.
Ваша проблема здесь, скорее всего, индексация.
Пожалуйста, покажите нам все индексы и ключи в этих таблицах. И планы запросов
Примечание: этот вопрос был бы близок к StackOverflow, так как он сейчас является дубликатом ... COUNT (1) против COUNT (*) - это еще один разрушенный миф.
источник
join
иwhere
предложением. Я оптимизирую длительные запросы все время, и иногда запросы с использованиемwhere
предложения работают лучше, чем те, которые используютсяjoin
в 70 раз. Если бы это было так просто и понятно, жизнь была бы всеми радугами и единорогами. И это не о каком-то древнем неясном движке - сейчас я смотрю на 70-кратное преимуществоwhere
предложения в SQL 2012.where
запрос предложения выполняется в большом пакете, частью которого он должен быть, он значительно опережаетjoin
запрос. Запросы SQL не выполняются в вакууме - на них влияет остальная часть полезной нагрузки сервера, и частоwhere
запросы запросов выполняются довольно хорошо, что раздражает, посколькуjoin
синтаксис действительно намного чище.Вы должны рефакторинг запроса в целом
Попробуйте выполнить предложения WHERE ранее, а потом - СОЕДИНЕНИЯ
Даже если вы выполняете план EXPLAIN для этого рефакторизованного запроса, и он выглядит хуже, чем ваш оригинал, попробуйте его в любом случае. Временные таблицы, созданные внутри, будут выполнять декартовы объединения, но эти таблицы меньше для работы.
Я получил эту идею из этого видео на YouTube .
Я опробовал принципы из видео в очень сложном вопросе в StackOverflow и получил награду в 200 баллов.
@gbn упомянул, что у вас есть правильные индексы. В этом случае, пожалуйста, проиндексируйте созданный столбец в MasterTable.
Попробуйте!
ОБНОВЛЕНИЕ 2011-06-24 22:31 EDT
Вы должны выполнить эти запросы:
Если NullRoles X 20 <AllRoles (другими словами, если NullRoles меньше 5% строк таблицы), вы должны создать неуникальный индекс Роль в UserTable. В противном случае будет достаточно полной таблицы UserTable, поскольку оптимизатор запросов может исключить использование индекса.
ОБНОВЛЕНИЕ 2011-06-25 12:40 ПО ВОСТОЧНОМУ ВРЕМЕНИ
Поскольку я являюсь администратором баз данных MySQL, мой метод ведения дел не требует доверия к оптимизатору запросов MySQL через позитивный пессимизм и консервативность. Таким образом, я попытаюсь реорганизовать запрос или создать необходимые покрывающие индексы, чтобы избавиться от скрытых вредных привычек MySQL Query Optimizer. Ответ @ gbn кажется более полным в том, что SQL Server может иметь больше «здравомыслия» при оценке запросов.
источник
У нас была [Детальная] таблица около 75M строк; таблица [Master] около 400 тыс. строк и связанная таблица [Item], в которой было 7 строк - всегда и навсегда. В нем хранился небольшой набор «Номера предметов» (1-7) и моделировалась бумажная форма, миллионы которых печатались и распространялись каждый месяц. Самый быстрый запрос был тот, о котором вы меньше всего задумывались в первую очередь, включающий использование декартового объединения. IIRC, это было что-то вроде:
Несмотря на то, что между [Item] и [Detail] существует логическая связь «id», CROSS JOIN работал лучше, чем INNER JOIN.
СУБД была Teradata с ее технологией MPP и IDR, какова была схема индексации. Таблица из 7 строк не имела индекса, так как TABLE SCAN всегда показывал лучшие результаты.
источник