Якщо ви маєте справу з великими базами даних, що краще, IN
або OR
в SQL Where
-клаузі?
Чи є різниця в тому, як вони виконуються?
Якщо ви маєте справу з великими базами даних, що краще, IN
або OR
в SQL Where
-клаузі?
Чи є різниця в тому, як вони виконуються?
Відповіді:
Я припускаю, що ви хочете знати різницю продуктивності між такими:
WHERE foo IN ('a', 'b', 'c')
WHERE foo = 'a' OR foo = 'b' OR foo = 'c'
Відповідно до посібника для MySQL, якщо значення постійніIN
сортує список, а потім використовує двійковий пошук. Я б міг уявити, що OR
оцінює їх один за одним у певному порядку. Так IN
швидше за деяких обставин.
Найкращий спосіб знати - профайлювати як у своїй базі даних конкретні дані, щоб побачити, що швидше.
Я спробував обидва на MySQL зі 1000000 рядками. Коли стовпчик індексується, різниці в продуктивності не помітна - обидва майже миттєві. Коли стовпець не індексується, я отримав ці результати:
SELECT COUNT(*) FROM t_inner WHERE val IN (1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000);
1 row fetched in 0.0032 (1.2679 seconds)
SELECT COUNT(*) FROM t_inner WHERE val = 1000 OR val = 2000 OR val = 3000 OR val = 4000 OR val = 5000 OR val = 6000 OR val = 7000 OR val = 8000 OR val = 9000;
1 row fetched in 0.0026 (1.7385 seconds)
Тож у цьому випадку метод, що використовує АБО, приблизно на 30% повільніше. Додавання більше термінів робить різницю більшою. Результати можуть залежати від інших баз даних та інших даних.
IN
методу полегшує оптимізацію, ніж цілий букет, можливо, супутні OR
пропозиції. Я був би здивований, якщо є двигун, де OR
метод швидший, але я не здивований, що бувають випадки, коли АБО повільніше.
OR
s на IN
?
Найкращий спосіб це дізнатися - це переглянути План виконання.
Я спробував це з Oracle , і це було точно так само.
CREATE TABLE performance_test AS ( SELECT * FROM dba_objects );
SELECT * FROM performance_test
WHERE object_name IN ('DBMS_STANDARD', 'DBMS_REGISTRY', 'DBMS_LOB' );
Незважаючи на те, що запит використовується IN
, План виконання говорить, що він використовує OR
:
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8 | 1416 | 163 (2)| 00:00:02 |
|* 1 | TABLE ACCESS FULL| PERFORMANCE_TEST | 8 | 1416 | 163 (2)| 00:00:02 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_NAME"='DBMS_LOB' OR "OBJECT_NAME"='DBMS_REGISTRY' OR
"OBJECT_NAME"='DBMS_STANDARD')
INLIST ITERATOR
операцію, яку він би вибрав, якби був індекс, який він міг би використовувати. Все-таки, коли я спробував це, і те, IN
і в OR
кінцевому підсумку з тим же планом виконання.
Оператору АБО потрібен набагато складніший процес оцінювання, ніж конструкція IN, оскільки він дозволяє багато умов, а не тільки таких, як IN.
Ось як те, що ви можете використовувати з ІЛИ, але які не сумісні з IN: більше. більший чи рівний, менший, менший чи рівний, LIKE та ще щось подібне до оракула REGEXP_LIKE. Крім того, врахуйте, що умови не завжди можуть порівнювати одне і те ж значення.
Для оптимізатора запитів простіше керувати оператором IN, оскільки це лише конструкція, яка визначає оператор АБО у кількох умовах з оператором = на одне значення. Якщо ви використовуєте оператор АБО, оптимізатор може не враховувати, що ви завжди використовуєте оператор = з одним і тим же значенням, і, якщо він не виконує більш глибоку і набагато складнішу розробку, він, ймовірно, може виключити, що може бути тільки = оператори для однакових значень у всіх задіяних умовах з подальшим виключенням оптимізованих методів пошуку, таких як уже згаданий бінарний пошук.
[EDIT] Можливо, оптимізатор може не реалізувати оптимізований процес оцінки IN, але це не виключає, що одного разу це могло статися (з оновленням версії бази даних). Тож якщо ви використовуєте оператор АБО, оптимізована розробка не буде використана у вашому випадку.
OR
має сенс (з точки зору читабельності), коли порівняно менше значень.
IN
корисний esp. коли у вас є динамічне джерело, з яким потрібно порівнювати значення.
Інша альтернатива - використання a JOIN
з тимчасовою таблицею.
Я не думаю, що ефективність не повинна бути проблемою, якщо у вас є необхідні показники.
Я зробив запит SQL у великій кількості АБО (350). Postgres роблять це 437,80 мс .
Тепер використовуйте IN:
23.18ms