IN против OR Oracle, что быстрее?

17

Я разрабатываю приложение, которое обрабатывает многие данные в базе данных Oracle.
В некоторых случаях мне нужно получить много объектов на основе определенного списка условий, и я использую SELECT ...FROM.. WHERE... IN... , но выражение IN просто принимает список, размер которого не превышает 1000 элементов.

Итак, вместо этого я использую выражение OR , но, как я вижу, возможно, этот запрос (используя OR ) медленнее, чем IN (с тем же списком условий). Это правильно? И если да, то как повысить скорость запроса?     

задан Đinh Hồng Châu 29.06.2011 в 03:38
источник

5 ответов

27

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

Лучший вариант, чем IN или OR , - это присоединиться к таблице, содержащей нужные вам значения (или не хотите). Эта таблица для сравнения может быть получена, временная или уже существующая в вашей схеме.     

ответ дан OMG Ponies 29.06.2011 в 03:48
источник
7

В этом случае я бы сделал следующее:

  1. Создать глобальную временную таблицу с одним столбцом
  2. Заполните эту таблицу своим списком из внешнего источника (и быстро - еще одно обсуждение)
  3. Сделайте свой запрос, присоединив временную таблицу к другой таблице (рассмотрите динамическую выборку, поскольку временная таблица не будет иметь хорошую статистику).

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

    
ответ дан WW. 29.06.2011 в 04:17
источник
2

Я бы поставил под сомнение весь подход. Клиент SP должен отправить 100000 идентификаторов. Откуда клиент получает эти идентификаторы? В любом случае отправка такого большого количества идентификаторов, как параметр proc, будет стоить значительно.

    
ответ дан oazabir 04.07.2011 в 19:34
источник
2

Oracle внутренне конвертирует списки IN в списки ORs так или иначе, поэтому действительно не должно быть различий в производительности. Единственное различие заключается в том, что Oracle должен преобразовывать INs, но имеет более длинные строки для синтаксического анализа, если вы сами поставляете OR.

Вот как вы это тестируете.

CREATE TABLE my_test (id NUMBER);

SELECT 1 
FROM my_test
WHERE id IN (1,2,3,4,5,6,7,8,9,10,
             21,22,23,24,25,26,27,28,29,30,
             31,32,33,34,35,36,37,38,39,40,
             41,42,43,44,45,46,47,48,49,50,
             51,52,53,54,55,56,57,58,59,60,
             61,62,63,64,65,66,67,68,69,70,
             71,72,73,74,75,76,77,78,79,80,
             81,82,83,84,85,86,87,88,89,90,
             91,92,93,94,95,96,97,98,99,100
             );

SELECT sql_text, hash_value
FROM v$sql 
WHERE sql_text LIKE '%my_test%';

SELECT operation, options, filter_predicates
FROM v$sql_plan
WHERE hash_value = '1181594990'; -- hash_value from previous query
  

ВЫБОР ЗАЯВЛЕНИЯ
  TABLE ACCESS FULL («ID» = 1 ИЛИ «ID» = 2 ИЛИ «ID» = 3 ИЛИ «ID» = 4 ИЛИ «ID» = 5   ИЛИ «ИД» = 6 ИЛИ «ИД» = 7 ИЛИ «ИД» = 8 ИЛИ «ИД» = 9 ИЛИ «ИД» = 10 ИЛИ «ИД» = 21 ИЛИ   «ID» = 22 ИЛИ «ID» = 23 ИЛИ «ИД» = 24 ИЛИ «ИД» = 25 ИЛИ «ИД» = 26 ИЛИ «ИД» = 27 ИЛИ   «ID» = 28 ИЛИ «ID» = 29 ИЛИ «ИД» = 30 ИЛИ «ИД» = 31 ИЛИ «ИД» = 32 ИЛИ «ИД» = 33 ИЛИ   «ID» = 34 ИЛИ «ID» = 35 ИЛИ «ID» = 36 ИЛИ «ID» = 37 ИЛИ «ID» = 38 ИЛИ «ID» = 39 ИЛИ   «ID» = 40 ИЛИ «ID» = 41 ИЛИ «ID» = 42 ИЛИ «ID» = 43 ИЛИ «ID» = 44 ИЛИ «ID» = 45 ИЛИ   «ID» = 46 ИЛИ «ID» = 47 ИЛИ «ID» = 48 ИЛИ «ID» = 49 ИЛИ «ID» = 50 ИЛИ «ID» = 51 ИЛИ   «ID» = 52 ИЛИ «ID» = 53 ИЛИ «ID» = 54 ИЛИ «ID» = 55 ИЛИ «ID» = 56 ИЛИ «ID» = 57 ИЛИ   «ID» = 58 ИЛИ «ID» = 59 ИЛИ «ID» = 60 ИЛИ «ID» = 61 ИЛИ «ID» = 62 ИЛИ «ID» = 63 ИЛИ   «ID» = 64 ИЛИ «ID» = 65 ИЛИ «ID» = 66 ИЛИ «ID» = 67 ИЛИ «ID» = 68 ИЛИ «ID» = 69 ИЛИ   «ИД» = 70 ИЛИ «ИД» = 71 ИЛИ «ИД» = 72 ИЛИ «ИД» = 73 ИЛИ «ИД» = 74 ИЛИ «ИД» = 75 ИЛИ   «ID» = 76 ИЛИ «ID» = 77 ИЛИ «ID» = 78 ИЛИ «ID» = 79 ИЛИ «ID» = 80 ИЛИ «ID» = 81 ИЛИ   «ИД» = 82 ИЛИ «ИД» = 83 ИЛИ «ИД» = 84 ИЛИ «ИД» = 85 ИЛИ «ИД» = 86 ИЛИ «ИД» = 87 ИЛИ   «ID» = 88 ИЛИ «ID» = 89 ИЛИ «ID» = 90 ИЛИ «ID» = 91 ИЛИ «ID» = 92 ИЛИ «ID» = 93 ИЛИ   «ID» = 94 ИЛИ «ID» = 95 ИЛИ «ID» = 96 ИЛИ «ID» = 97 ИЛИ «ID» = 98 ИЛИ «ID» = 99 ИЛИ   "ID" = 100)

    
ответ дан jva 27.07.2012 в 16:47
источник
1

Если вы создаете таблицу с помощью первичного ключа:

CREATE TABLE my_test (id NUMBER,
CONSTRAINT PK PRIMARY KEY (id));

и пройти через те же самые SELECT, чтобы запустить запрос с несколькими значениями IN, а затем получить план выполнения с помощью хэш-значения, что вы получаете:

SELECT STATEMENT
INLIST ITERATOR
INDEX                  RANGE SCAN

Это означает, что если у вас есть список IN и используется с столбцом PK, Oracle сохраняет этот список внутренне как «INLIST», потому что более эффективно обрабатывать это, а не преобразовывать его в ORs, как в случай неиндексированной таблицы.

Я использовал Oracle 10gR2 выше.

    
ответ дан TrevorH 17.05.2013 в 13:42
источник