Подтвердить что ты не робот

Что обеспечивает лучшую производительность одного большого соединения или нескольких запросов?

У меня есть таблица, называемая порядком. одна колонка на заказ customer_id
У меня есть таблица, называемая клиентами с 10 полями

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

Вариант 1:

а. первая таблица заказов запросов. б. зацикливать записи и запросить таблицу лиц, чтобы получить записи для человека

это будет что-то вроде:

 Select * from APplications

 Select * from Customer where id = 1
 Select * from Customer where id = 2
 Select * from Customer where id = 3
 Select * from Customer where id = etc . . .

Вариант 2:

а. выполнить объединение во всех полях

его очевидное # 2, потому что вы делаете только один запрос по сравнению с запросами 1 + [numberOforders] (может быть сотни или более)

Это будет что-то вроде:

 Select * from Applications a, Customers c
 Innerjoin c.id = a.customerID

Мой главный вопрос: что, если бы у меня было 10 других таблиц, которые были вне таблицы заказов (аналогично клиенту), где у вас был идентификатор в таблице заказов. если вы сделаете один запрос, который объединяет эти 10 таблиц или в какой-то момент, он неэффективен для этого:

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

4b9b3361

Ответ 1

Я согласен со всеми, кто сказал, что одно соединение, вероятно, будет более эффективным, даже с большим количеством таблиц. Это также снижает затраты на разработку, чем выполнение работы в коде приложения. Это предполагает, что таблицы соответствующим образом индексируются с индексом в каждом столбце внешнего ключа и (конечно) индексом в каждом столбце первичного ключа.

Лучше всего сначала попробовать самый простой подход (большое объединение) и посмотреть, насколько хорошо он работает. Если все будет хорошо, тогда здорово - все готово. Если он работает плохо, профайл запроса и поиск отсутствующих индексов в ваших таблицах.

Ваш вариант №1 вряд ли будет работать хорошо из-за количества сетевых поездок (как упоминалось выше). Это иногда называется проблемой "выбрать N + 1" - вы делаете один SELECT, чтобы получить список N приложений, а затем выполните N SELECT в цикле, чтобы получить клиентов. Этот цикл записи по времени является естественным для программистов приложений; но SQL работает намного лучше, когда вы работаете с целыми наборами данных одновременно.

Если параметр № 2 медленный, даже с хорошей индексацией, вы можете захотеть взглянуть на кеширование. Вы можете кэшировать в базе данных (используя сводную таблицу или материализованное/индексированное представление), в приложении (если имеется достаточное количество ОЗУ) или на выделенном сервере кеширования, таком как memcached. Конечно, это зависит от того, насколько актуальны ваши результаты запроса. Если все должно быть полностью обновлено, тогда любой кеш должен обновляться всякий раз, когда базовые таблицы обновляются - он становится сложным и становится менее полезным.

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

В зависимости от вашей СУБД, еще одна вещь, о которой стоит подумать, - это влияние этого запроса на другие запросы, попадающие в одну и ту же базу данных. Если ваша СУБД позволяет читателям блокировать писателей, тогда этот запрос может предотвратить обновление таблиц, если требуется много времени для запуска. Это было бы плохо. У Oracle нет этой проблемы, и SQL Server не запускается в режиме "read commit snapshot". Однако я не знаю о MySQL.

Ответ 2

Если этот customer_id уникален в вашей таблице клиентов (а другие идентификаторы уникальны в других таблицах), поэтому ваш запрос возвращает только 1 строку для каждого приложения, тогда выполнение одного SELECT, безусловно, более эффективно.

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

ИЗМЕНИТЬ
Я попробовал это с Oracle PL/SQL с 50 000 приложений и 50 000 подходящих клиентов.

Решение с выбором всего в одном запросе заняло
0.172 s

Решение с выбором каждого клиента в одном SELECT заняло 1.984 s

И это, скорее всего, ухудшается с другими клиентами или при доступе по сети.

Ответ 3

Единственное соединение будет, по-моему, еще быстрее, потому что СУБД всегда будет выполнять предложения where до того, как будут выполняться объединения. Это означает, что до и после соединения все задействованные таблицы уже были сокращены до минимально возможного размера.

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

Ключевым моментом здесь является то, что перед объединением все таблицы сокращаются до минимального размера, и мы используем внутренние соединения. Если оба эти условия меняются (некоторые внешние соединения в порядке), то у вас могут быть проблемы.

Ответ 4

должен ли вы сделать один запрос, который объединяет эти 10 таблиц или в какой-то момент это неэффективно

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

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

Ответ 5

Одно соединение должно быть быстрее по двум основным причинам.

Если вы запрашиваете по сети, то вместо использования одного запроса есть накладные расходы.

Соединение будет оптимизировано внутри СУБД с использованием оптимизатора запросов, поэтому будет быстрее, чем выполнение нескольких запросов.