#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 раз каждый и не заметил какой-либо существенной разницы в скоростях выполнения. Затем я запустил план объяснения и получил меньшее количество байтов для первого запроса, что меня удивило. Сегодня, когда я объясняю план по обоим запросам, я получаю идентичную статистику.