JOIN запросы против нескольких запросов

Запросы JOIN быстрее, чем несколько запросов? (Вы запускаете свой основной запрос, а затем запускаете много других SELECT на основе результатов вашего основного запроса)

Я спрашиваю, потому что ПРИСОЕДИНИТЬСЯ к ним будет усложнять LOT дизайн моего приложения

Если они быстрее, может ли кто-нибудь приблизительно приблизиться к тому, сколько? Если это 1.5x, мне все равно, но если это 10x, я думаю, что да.

    Это слишком неопределенно, чтобы дать вам ответ, относящийся к вашему конкретному делу. Это зависит от многих вещей. Джефф Атвуд (основатель этого сайта) на самом деле написал об этом . По большей части, хотя, если у вас есть правильные индексы, и вы правильно делаете свои JOINs, обычно будет быстрее совершить 1 поездку, чем несколько.

    Для внутренних объединений один запрос имеет смысл, поскольку вы получаете только соответствующие строки. Для левых объединений несколько запросов намного лучше … посмотрите на следующий тест, который я сделал:

    1. Одиночный запрос с 5 Соединениями

      запрос: 8.074508 секунд

      размер результата: 2268000

    2. 5 запросов подряд

      время комбинированного запроса: 0.00262 секунды

      размер результата: 165 (6 + 50 + 7 + 12 + 90)

    ,

    Обратите внимание, что мы получаем те же результаты в обоих случаях (6 x 50 x 7 x 12 x 90 = 2268000)

    левые соединения используют экспоненциально больше памяти с избыточными данными.

    Предел памяти может быть не таким уж плохим, если вы выполняете только объединение двух таблиц, но обычно три или более, и это стоит разных запросов.

    В качестве примечания, мой сервер MySQL находится рядом с моим сервером приложений … поэтому время соединения незначительно. Если ваше время соединения в секундах, то, возможно, есть преимущество

    Фрэнк

    Я на самом деле пришел к этому вопросу, ища ответ самостоятельно, и, прочитав эти ответы, могу только согласиться с тем, что лучший способ сравнить производительность запросов БД – это получение чисел в реальном мире, потому что нужно учитывать только многие переменные НО, я также думаю, что сравнение чисел между ними не приводит ни к чему хорошему почти во всех случаях. Я имею в виду, что числа всегда следует сравнивать с приемлемым числом и определенно не сравнивать друг с другом.

    Я могу понять, если один из способов запроса составляет 0,02 секунды, а другой – 20 секунд, это огромная разница. Но что, если один из способов запроса занимает 0,0000000002 секунды, а другой занимает 0,0000002 секунды? В обоих случаях один из способов – колоссальный в 1000 раз быстрее, чем другой, но действительно ли он по-прежнему «колоссальный» во втором случае?

    Итог, как я лично вижу: если он работает хорошо, подойдите к простому решению.

    Был ли быстрый тест, выбрав одну строку из таблицы из 50 000 строк и соединившись с одной строкой из таблицы из 100 000 строк. В основном выглядели:

    $id = mt_rand(1, 50000); $row = $db->fetchOne("SELECT * FROM table1 WHERE id = " . $id); $row = $db->fetchOne("SELECT * FROM table2 WHERE other_id = " . $row['other_id']); 

    против

     $id = mt_rand(1, 50000); $db->fetchOne("SELECT table1.*, table2.* FROM table1 LEFT JOIN table1.other_id = table2.other_id WHERE table1.id = " . $id); 

    Два метода select заняли 3,7 секунды для 50 000 чтений, тогда как JOIN занял 2,0 секунды на моем домашнем медленном компьютере. INNER JOIN и LEFT JOIN не повлияли. Получение нескольких строк (например, с помощью IN SET) дало аналогичные результаты.

    Создавайте как отдельные запросы, так и объединения, а затем время каждого из них – ничего не помогает больше, чем реальные числа.

    Тогда еще лучше – добавьте «EXPLAIN» в начало каждого запроса. Это расскажет вам, сколько подзапросов MySQL использует для ответа на ваш запрос на данные и сколько строк сканируется для каждого запроса.

    В зависимости от сложности базы данных по сравнению с сложностью разработчика, может быть проще выполнять множество вызовов SELECT.

    Попробуйте запустить статистику базы данных как для JOIN, так и для нескольких SELECT. Посмотрите, работает ли JOIN в вашей среде быстрее / медленнее, чем SELECT.

    Опять же, если изменить его на JOIN будет означать дополнительный день / неделю / месяц работы dev, я бы придерживался нескольких SELECT

    Ура,

    BLT

    Реальный вопрос: имеют ли эти записи отношения « один к одному» или отношения « один ко многим» ?

    Ответ TLDR:

    Если один-к-одному, используйте оператор JOIN .

    Если один-ко-многим, используйте один (или несколько) SELECT с оптимизацией кода на стороне сервера.

    Почему и как использовать SELECT для оптимизации

    SELECT ‘(с несколькими запросами вместо объединений) в большой группе записей на основе отношения «один ко многим» обеспечивает оптимальную эффективность, поскольку JOIN ‘ ing имеет проблему экспоненциальной утечки памяти. Захватите все данные, затем используйте серверный язык сценариев для его сортировки:

     SELECT * FROM Address WHERE Personid IN(1,2,3); 

    Результаты:

     Address.id : 1 // First person and their address Address.Personid : 1 Address.City : "Boston" Address.id : 2 // First person's second address Address.Personid : 1 Address.City : "New York" Address.id : 3 // Second person's address Address.Personid : 2 Address.City : "Barcelona" 

    Здесь я получаю все записи в одном отборе. Это лучше, чем JOIN , который будет получать небольшую группу этих записей по одному за раз в качестве подкомпонента другого запроса. Затем я разбираю его с серверным кодом, который выглядит примерно так …

     Address[] = $address; } ?> 

    Когда не использовать JOIN для оптимизации

    JOIN большой группы записей на основе взаимно-однозначного отношения с одной единственной записью обеспечивает оптимальную эффективность по сравнению с несколькими SELECT , один за другим, которые просто получают следующий тип записи.

    Но JOIN неэффективен при получении записей с отношением «один ко многим».

    Пример. В блогах базы данных есть 3 таблицы интересов, Blogpost, тег и комментарий.

     SELECT * from BlogPost LEFT JOIN Tag ON Tag.BlogPostid = BlogPost.id LEFT JOIN Comment ON Comment.BlogPostid = BlogPost.id; 

    Если есть 1 blogpost, 2 тега и 2 комментария, вы получите результаты, такие как:

     Row1: tag1, comment1, Row2: tag1, comment2, Row3: tag2, comment1, Row4: tag2, comment2, 

    Обратите внимание, как каждая запись дублируется. Итак, 2 комментария и 2 тега – 4 строки. Что, если у нас есть 4 комментария и 4 тега? Вы не получаете 8 строк – вы получаете 16 строк:

     Row1: tag1, comment1, Row2: tag1, comment2, Row3: tag1, comment3, Row4: tag1, comment4, Row5: tag2, comment1, Row6: tag2, comment2, Row7: tag2, comment3, Row8: tag2, comment4, Row9: tag3, comment1, Row10: tag3, comment2, Row11: tag3, comment3, Row12: tag3, comment4, Row13: tag4, comment1, Row14: tag4, comment2, Row15: tag4, comment3, Row16: tag4, comment4, 

    Добавьте больше таблиц, больше записей и т. Д., И эта проблема быстро раздуется до сотен строк, все из которых заполнены в основном избыточными данными.

    Что эти дубликаты стоят вам? Память (на сервере SQL и код, который пытается удалить дубликаты) и сетевые ресурсы (между SQL-сервером и вашим кодовым сервером).

    Источник: https://dev.mysql.com/doc/refman/8.0/en/nested-join-optimization.html ; https://dev.mysql.com/doc/workbench/en/wb-relationship-tools.html

    По моему опыту, я обнаружил, что быстрее запускать несколько запросов, особенно при получении больших наборов данных.

    При взаимодействии с базой данных из другого приложения, например PHP, есть аргумент одной поездки на сервер по многим причинам.

    Существуют и другие способы ограничить количество поездок на сервер и все еще запускать несколько запросов, которые часто не только быстрее, но и облегчают чтение приложения, например mysqli_multi_query.

    Я не новичок, когда речь заходит о SQL, я думаю, что разработчики, особенно юниоры, склонны тратить много времени на то, чтобы писать очень умные объединения, потому что они выглядят умными, тогда как существуют действительно умные способы извлечения данных, которые выглядят просто.

    Последний абзац был личным мнением, но я надеюсь, что это поможет. Я согласен с другими, но кто скажет, что вы должны сравнивать. Ни один из подходов не является серебряной пhive.

    Будет ли это быстрее с точки зрения пропускной способности? Вероятно. Но он также потенциально блокирует больше объектов базы данных за раз (в зависимости от вашей базы данных и вашей схемы) и тем самым уменьшает параллелизм. По моему опыту, люди часто вводят в заблуждение аргумент «меньшее количество обращений к базам данных», когда в действительности на большинстве OLTP-систем, где firebase database находится в одной и той же локальной сети, реальным узким местом редко является сеть.

    Вот ссылка с 100 полезными запросами, они протестированы в базе данных Oracle, но помните, что SQL – это стандарт, который отличается от Oracle, MS SQL Server, MySQL и других баз данных – это диалект SQL:

    http://javaforlearn.com/100-sql-queries-learn/

    Есть несколько факторов, которые означают, что нет двоичного ответа. Вопрос о том, что лучше всего подходит для производительности, зависит от вашей среды. Кстати, если ваш единственный выбор с идентификатором не является второстепенным, что-то может быть неправильным в вашей конфигурации.

    Реальный вопрос: как вы хотите получить доступ к данным. Single выбирает поддержку позднего связывания. Например, если вам нужна информация о сотрудниках, вы можете выбрать ее из таблицы Сотрудники. Внешние ключевые отношения могут использоваться для извлечения связанных ресурсов в более позднее время и по мере необходимости. У выбора будет уже установлен ключ, чтобы они были очень быстрыми, и вам нужно только получить то, что вам нужно. Латентность сети всегда должна учитываться.

    Соединения будут извлекать все данные одновременно. Если вы создаете отчет или заполняете сетку, это может быть именно то, что вы хотите. Скомпилированные и оптометрические соединения просто будут быстрее, чем отдельные варианты в этом сценарии. Помните, что присоединение Ad-hoc может быть не таким быстрым – вы должны скомпилировать их (в хранимую процедуру). Ответ на скорость зависит от плана выполнения, который точно определяет, какие шаги предпринимает СУБД для извлечения данных.

    Да, один запрос с использованием JOINS будет быстрее. Хотя вы не знаете взаимоотношений таблиц, которые вы запрашиваете, размер вашего набора данных или первичные ключи, почти невозможно сказать, насколько быстрее.

    Почему бы не проверить оба сценария, тогда вы точно знаете …

    Нужно ли использовать соединение, прежде всего, о том, имеет ли смысл соединение . Только в этот момент производительность даже должна быть рассмотрена, так как почти все другие случаи приведут к значительно худшей производительности.

    Различия в производительности будут в значительной степени связаны с тем, как связана информация, которую вы запрашиваете. Объединяет работу, и они быстрые, когда данные связаны, и вы индексируете материал правильно, но они часто приводят к некоторой избыточности и иногда к большему количеству результатов, чем это необходимо. И если ваши наборы данных напрямую не связаны друг с другом, приклеивание их в одном запросе приведет к тому, что называется декартовым произведением (в основном, всеми возможными комбинациями строк), которое почти никогда не является тем, что вы хотите.

    Это часто связано со многими отношениями «один-ко-многим». Например, в ответе HoldOffHunger упоминается один запрос для сообщений, тегов и комментариев. Комментарии относятся к сообщению, как и tags … но tags не связаны с комментариями.

     +------------+ +---------+ +---------+ | comment | | post | | tag | |------------|* 1|---------|1 *|---------| | post_id |-----| post_id |-----| post_id | | comment_id | | ... | | tag_id | | user_id | | | | ... | | ... | | | | ... | +------------+ +---------+ +---------+ 

    В этом случае для этого недвусмысленно лучше как минимум два отдельных запроса. Если вы попытаетесь присоединиться к тегам и комментариям, потому что между ними нет прямой связи, вы получаете все возможные комбинации тегов и комментариев. many * many == manymany . Помимо этого, поскольку сообщения и tags не связаны друг с другом, вы можете выполнять эти два запроса параллельно, что приводит к потенциальному выигрышу.

    Давайте рассмотрим другой сценарий: вы хотите, чтобы комментарии были прикреплены к сообщению, и контактные данные комментаторов.

      +----------+ +------------+ +---------+ | user | | comment | | post | |----------|1 *|------------|* 1|---------| | user_id |-----| post_id |-----| post_id | | username | | user_id | | ... | | ... | | ... | +---------+ +----------+ +------------+ 

    Здесь вы должны рассмотреть вопрос о присоединении. Помимо более естественного запроса, большинство систем баз данных (включая MySQL) имеют множество умных людей, которые много работали над оптимизацией запросов. Для отдельных запросов, поскольку каждый запрос зависит от результатов предыдущего, запросы не могут выполняться параллельно, и общее время становится не просто фактическим временем выполнения запросов, но также временем, затрачиваемым на получение результатов, просеиванием через них для идентификаторов для следующего запроса, связывания строк и т. д.

    Давайте будем гением компьютера.