Какой оператор SQL быстрее?
SELECT TOP 2 c1.Price, c2.Price, ..... c49.Price, c50.Price
FROM Table1 AS c1, Table2 AS c2, ..... Table49 AS c49, Table50 AS c50
WHERE c1.Date = c2.Date AND c2.Date = c3.Date ..... c49.Date = c50.Date
ORDER BY c1.ID DESC
OR
SELECT TOP 2 c1.Price, c2.Price, ..... c49.Price, c50.Price
FROM (Table1 AS c1
INNER JOIN (Table2 AS c2
........
INNER JOIN (Table49 AS c49
INNER JOIN Table50 AS c50
ON c49.Date = c50.Date)
........
ON c2.FullDate__ = c3.FullDate__)
ON c1.FullDate__ = c2.FullDate__)
ORDER BY c1.ID DESC";
Обычно мне нужно извлекать 2 строки из каждой таблицы, чтобы периодически составлять сводку. Какая инструкция быстрее?
Что происходит с этими скобками? Почему это не «присоединиться к таблице 2 на c1.FullDate = c2.FullDate» и т. д.
Мда, раньше не замечал этих внутренних комментариев. Довольно круто. В любом случае я использую MS Access для прототипа, но я нахожусь в процессе перехода на MySQL (см. Мой предыдущий ответ), и эти фигурные скобки необходимы, иначе запрос не будет выполнен.


WHERE обычно лучше, но лучший способ - это От случая к случаю и бросить это в профилировщик, или еще проще отображать план выполнения. Люди часто имеют очень твердое мнение о том, какой подход является самым быстрым / лучшим в теории, но нет замены фактической настройке в соответствии с данными, с которыми вы действительно имеете дело, поскольку применимые теории меняются в зависимости от вашей нагрузки данных.
Если в вашем приложении еще нет реальные данные, попробуйте создать реалистичные данные о стрессе. Это по-прежнему будет полезно для тестирования. Затем запланируйте время для настройки, когда приложение будет запущено.
По возможности игнорируйте JOIN. С точки зрения производительности операторы соединения вообще неэффективны.
Предложение where также выполняет «соединение», но без использования ключевого слова join. Избегать объединений по соображениям производительности можно на этапе проектирования модели базы данных, не денормализуя определенные части вашей модели.
Этот ответ на 100% неверен. С правильными индексами JOIN очень эффективны.
Я никогда не слышал о СУБД с неэффективными соединениями (при индексировании).
Честно говоря, я думаю, что это было верно в некоторых старых версиях MySQL - до 3 ?. Конечно, многие из нас согласны с тем, что эта часть программного обеспечения на самом деле не была базой данных в каком-либо значимом смысле :-). Это совершенно не соответствует действительности ни в одной современной РСУБД.
Нет, это не на 100% неправильно! По умолчанию объединения неэффективны. Это факт. Однако если у вас есть две или более таблиц, которые часто объединяются, тогда столбцы, используемые для объединений во всех таблицах, должны иметь соответствующий индекс.
Прочтите это: sql-server-performance.com/tips/tuning_joins_p1.aspx Ссылка показывает, что вам нужно сделать дополнительные вещи, чтобы повысить производительность операторов соединения.
Вы заметили это предложение в следующей ссылке: «Это относится к исходному утверждению, что количество строк в таблице может повлиять на производительность JOIN».
С точки зрения производительности вашим программистам будет нелегко поддерживать бесперебойную работу, если ваша схема базы данных отстойна. Если у вас хорошая схема и плавное программирование, но вам нужна более высокая производительность, приобретите больше индексов или больше оборудования.
mnour, когда на странице написано, что «соединения неэффективны», они относятся к объединению таблиц в целом. Вопрос здесь относится к синтаксису, используемому для соединения (соединения SQL-92 против соединений SQL-86). Тот факт, что вы сопоставляете строки в предложении WHERE, не означает, что вы не выполняете JOIN.
Вы, вероятно, обнаружите, что механизм оптимизации SQL будет генерировать такой же внутренний запрос (если логика такая же), и в результате разницы не будет.
Как упоминалось другими, запустите это через профилировщик (например, анализатор запросов), чтобы определить разницу (если она есть).
Что быстрее, так это отсутствие 50 таблиц для начала. Объединение 50 таблиц могло бы быть приемлемым, но это крайне противоречивый дизайн и, вероятно, не самое удобное решение.
Разве вы не можете хранить свои данные в строках (или столбцах) одной (или меньшего числа) таблиц, а не в 50 таблицах ??!
да, интересное наблюдение из названий таблиц.
Думаю, почти наверняка недели в году, и, вероятно, их собирают откуда-то еще. Конечно, сценарий консолидации, прежде чем он попадет в точку, может показаться разумным.
Обычно база данных оптимизирует оба оператора, поэтому разница не будет такой большой. Но вы можете убедиться в этом, сравнив план объяснения для обоих запросов.
Одна вещь, которая могла бы оптимизировать запрос с соединениями (я не проверял это), - это наличие дополнительных ограничений (не ограничений соединения) в операторе соединения. Хотя это не рекомендуемый стиль, поскольку он четко не разделяет условия соединения и другие условия.
Например:
select *
from A a
join B b on b.x = a.y
where b.z = 'ok';
можно записать как
select *
from A a
join B b on b.x = a.y and b.z = 'ok';
Я бы сказал, что план оптимизатора / выполнения может иметь огромное влияние. если один приводит к сканированию таблицы, а другой не имеет большого значения. Я действительно не могу себе представить, что в общем случае оптимизатор превратит эти операторы в эквивалентные пути выполнения.
Если вы приложите снимок экрана с планами запросов и трассировку профилировщика, я буду рад сообщить вам, какой из них быстрее. В противном случае информации действительно недостаточно, чтобы ответить на вопрос.
Мне кажется, что оба имеют очень схожую производительность в SQL Server и что SQL-сервер оптимизирует оба для использования одного и того же плана запроса, но кто знает, возможно, соединение пятидесяти таблиц сводит оптимизатор с ума.
В целом я буду придерживаться семантики JOIN, потому что мне легче читать и поддерживать. Поперечное соединение очень подвержено ошибкам и встречается крайне редко.
Спасибо за ответы, ребята.
У меня нет доступа к Query Analyzer, так как в настоящее время я перемещаю эту базу данных из MS Access, где я делал быстрый прототип, для MySQL. Я считаю, что Query Analyzer доступно только на SQL Server, но я могу ошибаться, поэтому не могу прикрепить трассировку профилировщика.
Каждая таблица отличается (т.е. значения в ней уникальны, хотя имена столбцов могут быть одинаковыми) и используется отдельно для создания других объектов, но мне иногда нужно запускать сводку, которая собирает строки из каждой таблицы. Итак, я считаю, что мне нужно 50 таблиц, хотя я еще не детально изложил всю схему вещей и поэтому изучу ее. (p.s. Я новичок в базах данных и SQL, но не новичок в программировании). Мне также нужно учитывать последствия для размера памяти, если я должен был поместить всю информацию в одну таблицу, когда будет использоваться только небольшая ее часть.
Однако из того, что я собрал, разница не должна быть такой большой, поскольку 2 оператора, вероятно, будут скомпилированы для одного и того же внутреннего запроса. Я задал вопрос, желая знать, будет ли внутреннее устройство другим. Проведем тесты на реальных данных, чтобы выяснить это.
Кстати, будет ли иметь значение производительность двух операторов, если мы рассмотрим в уравнении одновременные запросы нескольких пользователей?
Вы не указываете ожидаемый объем ваших таблиц, но имейте в виду, что если запросы действительно оптимизируются для разных планов запросов, то то, что является самым быстрым при 100 строках в вашей таблице, может не совпадать с тем, когда у вас есть 100 000 строк или более.
Фактически, обычно мало что можно получить от навязчивой оптимизации для запросов с использованием таблиц, содержащих менее 10 000 записей, при условии, что у вас есть разумно спроектированные индексы и запросы. Однако где-то около 100 000 записей производительность плохо оптимизированных запросов начнет ухудшаться, как правило, катастрофически. Точная цифра зависит от размера строки и объема памяти на сервере, но нередко можно увидеть снижение производительности на порядок или больше при удвоении размера таблицы.
Как правило, это лучшая стратегия, чтобы не тратить время на второстепенные запросы к меньшим таблицам, усилия обычно могут быть потрачены с большей выгодой в другом месте. Однако агрессивно оптимизируйте любые запросы, которые работают с вашими основными таблицами, если ожидается, что они вырастут более чем на 10 000 строк. Обычно это означает использование экземпляра QA и загрузку с объемом, в 10 раз превышающим ожидаемый, для проверки фактического поведения.
Все разговоры о меньшем количестве столов заставили меня задуматься (спасибо, MarkR). я был просмотрел документацию MySQL за последние пару часов и понял что лучшим решением было бы создать новую сводную таблицу, в которой первые результаты. После этого я бы создал триггер, который обновил бы новую таблицу всякий раз, когда происходит вставка в одну из таблиц, к которой всегда прикасаются.
Еще одна идея, о которой я подумал, - это создание представления запроса. Однако кажется, что MySQL запускает базовый запрос к представлению при каждом его вызове. Я прав? Есть ли способ чтобы MySQL сохранил результирующую таблицу предварительно выполненного представления, а затем использовал триггер сказать представлению, когда обновлять таблицу? Есть ли какая-нибудь СУБД, которая это делает?
В SQL Server есть концепция индексированного представления, я не уверен, есть ли у MySQL эквивалент.
Оптимизация порядка соединения занимает экспоненциальное время. Каждый механизм базы данных просто выбирает небольшое количество возможных порядков соединения и оценивает лучший из них.
Похоже, вы всегда будете хотеть join ... on c*1*.Date = c*n*.Date для всех n.
Вы также захотите избавиться от имеющейся у вас чрезвычайно странной схемы базы данных.
Что случилось, когда вы попробовали?
Я имею в виду серьезно, у Query Analyzer есть небольшой таймер не зря. Разные структуры запросов иногда дают сильно разное время выполнения, часто без какой-либо интуитивной причины.
Напишите оба запроса. Испытайте их. Затем вернитесь и ответьте на свой вопрос.
Какой механизм базы данных SQL вы используете?