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

#sql #oracle #oracle11g

#sql #Oracle #oracle11g

Вопрос:

Пытаюсь понять последствия для производительности использования инструкции case, которая включает в себя предложение IN, содержащее несколько значений (запрос 1 ниже), по сравнению с одним логическим оператором меньше, чем (запрос 2 ниже). Должно ли предложение IN выполнять несколько логических проверок для данного поля? Например, предполагая, что строка не соответствует критериям первого запроса, равным 1, должно ли поле first_rating_number следующей записи иметь значение 2, затем 3, затем 4, если ни одно из них не присутствует? Будет ли это медленнее, чем first_rating_number < 5 (как во втором запросе)?

Я запустил план выполнения, и Oracle сообщает мне, что стоимость эквивалентна и что во втором запросе байты немного выше. Для меня это не имеет смысла. Заранее спасибо всем.

Редактировать — Дополнительная информация: Вчера я получал разные байты, при этом первый запрос показывал меньше. Сегодня оба плана отображают идентичную информацию о плане объяснения.

Количество строк: 1 261 914

Запрос 1 Объясняет план: Стоимость — 22 134; Байт — 3 785 742

Запрос 2 Объясняет план: Стоимость — 22 134; Байт — 3 785 742

 SELECT 
  CASE  WHEN first_rating_number = 1 THEN 'AAA' 
         WHEN first_rating_number IN (2,3,4) THEN 'AA' 
         WHEN first_rating_number IN (5,6,7) THEN 'A' 
         WHEN first_rating_number IN (8,9,10) THEN 'BBB' 
         WHEN first_rating_number IN (11,12,13) THEN 'BB'
         WHEN first_rating_number IN (14,15,16) THEN 'B'
         WHEN first_rating_number IN (17,18,19) THEN 'CCC'        
         WHEN first_rating_number IN (20) THEN 'CC'                     
         WHEN first_rating_number IN (22) THEN 'D'  END first_rating_category_test
  FROM tbl_IN_CLAUSE;

  
 SELECT 
  CASE  WHEN first_rating_number = 1 THEN 'AAA' 
         WHEN first_rating_number <5 THEN 'AA' 
         WHEN first_rating_number <8 THEN 'A' 
         WHEN first_rating_number <11 THEN 'BBB' 
         WHEN first_rating_number <14 THEN 'BB'
         WHEN first_rating_number <17 THEN 'B'
         WHEN first_rating_number <20 THEN 'CCC'        
         WHEN first_rating_number = 20 THEN 'CC'                     
         WHEN first_rating_number = 22 THEN 'D'  END first_rating_category_test
  FROM tbl_LESS_THAN;  

  

Комментарии:

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

2. Пожалуйста, предоставьте свой план объяснения для обоих запросов и укажите, сколько строк хранится в таблице (ах).

3. Это не то, что вы просили, но: если важна скорость (хотя в таком приложении не совсем понятно, почему это должно быть), возможно, вам лучше создать небольшую таблицу поиска с номером рейтинга и буквенными рейтингами, проиндексировать номер рейтинга (лучше: сделать его первичным ключом), проиндексировать номер рейтинга в tbl_less_than (лучше: сделать его внешним ключом) и использовать соединение, а не case выражение.

4. Проблема, которую я испытываю по поводу второго запроса, заключается в том, что давайте предположим, что рейтинговое число равно 4, оно меньше 5, но оно также меньше остальных значений, в этом случае ваш запрос становится основанным на последовательности, поскольку оператор case будет выполняться в порядке их записи, и вы можете получить неверный вывод (если второй регистр — это что-либо после второй позиции), при этом регистр первого запроса, в котором вы используете IN, будет давать вам точный ответ каждый раз.

Ответ №1:

Вы можете настроить тест для этого, если хотите, но логика подсказывает, что подход с неравенствами должен быть быстрее. (НАСКОЛЬКО быстрее, вы можете узнать только путем тестирования.)

Почему?

Потому что неравенство является единственным тестом. Для сравнения, x in (3, 4, 5, 6, 7) это пять тестов, и все пять должны быть опробованы по порядку, если x = 7 или если x их нет в списке. in Условие переписывается как x = 3 or x = 4 or x = 5 ... , и эти тесты не могут выполняться параллельно — они проверяются по одному за раз.

Комментарии:

1. Это были мои точные мысли, которые и побудили меня опубликовать проблему. Я выполнил запросы примерно по 10 раз каждый и не заметил какой-либо существенной разницы в скоростях выполнения. Затем я запустил план объяснения и получил меньшее количество байтов для первого запроса, что меня удивило. Сегодня, когда я объясняю план по обоим запросам, я получаю идентичную статистику.