Какое избранное заявление имеет лучшую производительность? - PullRequest
0 голосов
/ 26 августа 2010

Предположим, что master_table содержит много записей, и оба поля "id" в master_table, tableA, tableB, tableC и tableD одинаковы в деловом смысле.

Для 2 операторов выбора, показанных ниже,

Будут ли оба возвращать один и тот же набор результатов?

Какой из них будет иметь лучшую производительность?

Я думаю, что если tableA_tmp, tableB_tmp, tableC_tmp и tableD_tmp возвращают меньший набор результатов, SQL1 будет быстрее, чем SQL2, потому что oracle не нужно запрашивать tableA_tmp ,, tableB_tmp, tableC_tmp и tableD_tmp один раз для каждой записи master_table.

Но если и tableA_tmp, tableB_tmp, tableC_tmp и tableD_tmp возвращают большой набор результатов, SQL 2 будет намного быстрее, потому что стоимость объединения множества больших результатов значительно выше, чем запрос tableA_tmp ,, tableB_tmp, tableC_tmp иtableD_tmp один раз для каждой записи master_table.

Пожалуйста, исправьте меня, если у меня возникнет какое-либо недопонимание.Или любой другой метод предложил?

SQL1:

select 
        master_table.* ,
        tableA_tmp.cnt as tableA_cnt , 
        tableB_tmp.cnt as tableB_cnt ,  
        tableC_tmp.cnt as tableC_cnt ,  
        tableD_tmp.cnt as tableD_cnt 
    from
        master_table,
        (select  tableA.id as id, count(1) as cnt  from tableA group by tableA.id) tableA_tmp,
        (select  tableB.id as id, count(1) as cnt from tableB group by tableB.id) tableB_tmp,
        (select  tableC.id as id, count(1) as cnt from tableC group by tableC.id) tableC_tmp,
        (select  tableD.id as id, count(1) as cnt from tableD group by tableD.id) tableD_tmp
    where 
        master_table.id = tableA_tmp.id(+) and
        master_table.id = tableB_tmp.id(+) and
        master_table.id = tableC_tmp.id(+) and
        master_table.id = tableD_tmp.id(+) ;

SQL 2:

   select 
        master_table.* ,
        (select  count(*)  from tableA where tableA.id = master_table.id) as tableA_cnt,
        (select  count(*)  from tableB where tableB.id = master_table.id) as tableB_cnt,
        (select  count(*)  from tableC where tableC.id = master_table.id) as tableC_cnt,
        (select  count(*)  from tableD where tableD.id = master_table.id) as tableD_cnt
    from
        master_table;

Ответы [ 5 ]

3 голосов
/ 26 августа 2010

Объединения обычно лучше, чем встроенные запросы - встроенные запросы выполняются для каждой строки, возвращаемой из основного запроса.

Это означает, что (1) лучше, чем (2). В 99% случаев как минимум.

В некоторых случаях распределение данных и способы определения индексов могут сыграть роль в повышении эффективности времени выполнения запроса в сторону 2, но это происходит очень редко в средней базе данных.

3 голосов
/ 26 августа 2010

Ознакомьтесь с планом выполнения

1 голос
/ 26 августа 2010

Тот, кто выполняет работу в меньший промежуток времени.

0 голосов
/ 29 августа 2010

Если основная таблица и другие таблицы достаточно велики, SQL 1 будет быстрее. Причиной является сканирование таблицы. Сканирование таблиц обходится дорого, так как сканирование включает ввод-вывод. Первый запрос требует только одного сканирования каждой из таблиц tableA, tableB, tablec и tableD.

В SQL2 для каждого ключа в главной таблице таблицы tableA, tableB, tablec и tableD будут сканироваться отдельно. Если в основной таблице 10 строк, таблица tableA будет сканироваться 10 раз, tableB будет сканироваться 10 раз, tableC будет сканироваться 10 раз и так далее. Стоимость будет высокой.

Пример проиллюстрирует эту мысль. Предположим, что каждая таблица имеет 1000 записей, каждая с отдельным идентификатором. В первом запросе таблицы tableA, tableB, tablec и tableD будут сканироваться по одному разу, и результат будет объединен. Полученное количество строк будет большим, но будет отфильтровано за разумное время. В SQL2 каждая таблица tableA, tableB, tablec и tableD будет сканироваться 1000 раз каждая. Это очень дорого.

0 голосов
/ 27 августа 2010

Различные наборы результатов.Рассмотрим, если таблица А пуста.

В утверждении 1 tableA_tmp также будет пустым.При внешнем соединении будет возвращена строка, но значение tableA_tmp.cnt будет нулевым.

В операторе 2 счет будет выполнен и вернет нулевое значение.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...