Чи впливає порядок стовпців у пункті WHERE в MySQL на ефективність запитів?


38

У мене виникають проблеми з виконанням певних запитів до бази даних, які мають великі можливі набори результатів.

У запиті, про який я ANDпитаю, у пункті WHERE є три s

Чи має значення порядок пропозицій?

Як і в тому випадку, якщо я ставлю спочатку пункт ASI_EVENT_TIME (оскільки це видалить більшість результатів із будь-якого з пунктів.

Чи поліпшить це час виконання запиту?

ПИТАННЯ:

SELECT DISTINCT  activity_seismo_info.* 
FROM `activity_seismo_info` 
WHERE 
    activity_seismo_info.ASI_ACTIVITY_ID IS NOT NULL  AND 
    activity_seismo_info.ASI_SEISMO_ID IN (43,44,...,259) AND 
    (
        activity_seismo_info.ASI_EVENT_TIME>='2011-03-10 00:00:00' AND 
        activity_seismo_info.ASI_EVENT_TIME<='2011-03-17 23:59:59'
    ) 

ORDER BY activity_seismo_info.ASI_EVENT_TIME DESC

ПОЯСНЕННЯ запиту:

+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
| id | select_type | table   | type  | possible_keys             | key          | key_len | ref  | rows  | Extra                       |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
|  1 | SIMPLE      | act...o | range | act...o_FI_1,act...o_FI_2 | act...o_FI_1 | 5       | NULL | 65412 | Using where; Using filesort |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+

Використання:

PHP 5.2

MySQL 5.0.51a-3ubuntu5.4

Рушій 1.3

Симфонія 1.2.5


ЗАМОВЛЕННЯ - це, мабуть, що займає так довго. "Використання файлів" може бути дуже повільним. Я знайшов робити замовлення в логіці програми набагато швидше, ніж використовувати ORDER BY.
маклема

Це те саме питання я задав деякий час назад (перед цим сайтом) на stackoverflow. Перевірте посилання на відповіді, які я там отримав. stackoverflow.com/questions/3805863/…
Скотт

2
@maclema - Якщо ваша програма працює на набагато більш швидкій машині, ніж ваша база даних, ваше твердження, безумовно, не відповідає дійсності, не кажучи вже про безглузде навантаження на всю цю логіку сортування у вашій програмі. order byналежить до бази даних.
Джек Дуглас

Відповіді:


24

Я так не думаю. Оптимізатор запитів повинен бути досить розумним.

Ви можете спробувати переставити пропозиції WHERE і побачити, що EXPLAINS говорить вам те саме в кожному випадку.


Про те, що можна зробити для оптимізації цього запиту: чи є індекс ASI_EVENT_TIME? (це найважливіше, я думаю, для цього запиту, оскільки ви також сортуєте результати, використовуючи його).

Чи є індекси на двох інших полях (ASI_SEISMO_ID та ASI_ACTIVITY_ID)?

Було б корисно, якщо ви розмістили структуру таблиці.


Я ніколи не думав створювати індекс часу події. Я спробую це завтра на dev db і побачу, чи є помітна різниця.
Патрік

@Patrick Припускаючи, що всі інші запити, які використовують цей індекс, замовляють цю дату у порядку зменшення, ви також хочете замовити індексний ключ (activity_seismo_info.ASI_EVENT_TIME) у порядку зменшення.
Мет М

@MattM Я не знав, що ти можеш замовити індексний ключ. Дивовижно Якщо я замовляю індексний ключ, чи обов'язково це зашкодить впорядкуванню продуктивності у зворотному напрямку до того, що він гірший, ніж відсутність індексного ключа?
Патрік

@Patrick Ви маєте рацію. Мій мозок застряг у землі SQL Server. Ви можете вказати порядок сортування в MYSQL і він буде аналізувати, але він ігнорується. Усі індекси відсортовані у порядку зростання у MYSQL. Вибачте за непорозуміння.
Мет М

13

З документації :

Якщо таблиця має індекс з декількома стовпцями, оптимізатор може використовувати будь-який крайній лівий префікс індексу для пошуку рядків. Наприклад, якщо у вас індекс трьох стовпців на (col1, col2, col3), ви маєте індексовані можливості пошуку на (col1), (col1, col2) та (col1, col2, col3).

MySQL не може використовувати індекс, якщо стовпці не утворюють крайнього лівого префікса індексу.

Так, так, він повинен бути таким же, як порядок стовпців у складеному індексі .


4
Якщо в таблиці є індекс з декількома стовпцями, вибираючи стовпці з лівих питань, але порядок, у якому ви вибираєте, значення не має. Тож якщо у вас є індекс a, b, c, і ви, WHERE c = 'foo' AND a = 'bar' AND b = 'foobar'і індекс все ще придатний для використання.
texelate

10

Ні, це не має значення.

Оптимізатор робить купу простих перетворень відразу після того, як він розбирає SQL - це одне з них.


8

ДЕ ФОЙ І бар

оптимізує те саме, що і

ДЕ бар і фу

Однак,

ДЕ не рівний №1 І не рівний №2

Неможливо оптимізувати обидві частини. Наприклад,

ДЕ МІЖ 1 і 3 І b> 17

не може добре використовувати INDEX (a, b) або INDEX (b, a)

Щоб висловити його по-різному, будь-які тести "=" І разом у пункті WHERE використовуються спочатку, тоді можна обробити один не - "=" (IN, МЕЖ,> тощо). Не більше ніж один не може бути ефективно оптимізований.

У вашому запиті є 3 такі пропозиції.

Як виявляється, INDEX (EVENT_TIME) є, мабуть, найбільш корисним - він допоможе з одним з AND, і він може бути використаний, щоб уникнути "файлового ряду" для ORDER BY.

Якщо немає повторюваних рядків (чому б хек там був?), То позбудьтесь від DISTINCT. Це викликає ще більше зусиль.

Будь ласка, надайте ШОУ СТВОРИТИ ТАБЛИЦЮ та ПОКАЖИТИ СТАТУТ ТАБЛИЦІ, коли задаєте питання щодо ефективності

Оновлення ... Новіші версії (наприклад, MySQL 5.7) можуть у деяких випадках трактувати IN( list of constants )майже так само =. Щоб грати в безпеку, дотримуйтесь цього порядку (кожна частина - необов’язково):

  1. Будь-яка кількість =.
  2. Деякі INs.
  3. Максимум один діапазон.

1

MySQL, де йдеться про документи оптимізації :

Можливо, вам сподобається переписати запити, щоб зробити арифметичні операції швидшими, при цьому приносячи в жертву читабельність. Оскільки MySQL робить подібні оптимізації автоматично , ви часто можете уникати цієї роботи та залишати запит у більш зрозумілій та підтримуваній формі. Деякі з оптимізацій, виконаних MySQL, наступні:

  • ...

  • Для кожної таблиці в об'єднанні простіший БУДЬ побудований, щоб отримати швидку оцінку ДЕГО для таблиці, а також якнайшвидше пропустити рядки .

  • Кожен табличний індекс запитується, і найкращий індекс використовується, якщо оптимізатор не вважає, що ефективніше використовувати сканування таблиці . Свого часу сканування застосовувалося на основі того, чи найкращий показник охоплював більше 30% таблиці, але фіксований відсоток більше не визначає вибір між використанням індексу чи скануванням. Зараз оптимізатор є більш складним і базує свою оцінку на додаткових факторах, таких як розмір таблиці, кількість рядків та розмір блоку вводу / виводу.

Таким чином, оптимізатором запитів раціонально опускати HOW-порядок, ми використовували стовпці в запиті (не тільки MySQL, але і SQL є декларативною мовою, і ми повинні робити те, що ми хочемо, не так, як хочемо).

Однак я все ще люблю мати такий самий сорт для стовпців складеного ключа в запиті, але це іноді неминуче, наприклад, коли ми використовуємо ORM або ActiveRecord, в деяких рамках, таких як yii2, налаштування критеріїв відношення буде додано в кінці умова "on", але нам все ще потрібні можливості QueryBuilders в різних частинах програми.


-2

БУДЬ-ЯКОЕ поле, яке використовується у застереженнях WHERE / HAVING і має високу вибірковість (кількість унікальних значень / загальна кількість записів> 10% ~ 20%), ОБОВ'ЯЗКОВО бути індексовано.

Отже, якщо ваш ASI_EVENT_TIMEстовпець має багато можливих значень, спочатку проіндексуйте їх усі. Потім, як сказав @ypercube, спробуйте переставити їх і подивіться, що вам пояснює EXPLAIN. Повинні бути всі навколо однакові.

Крім того, хочете, щоб ви подивилися на індексацію фільтрів SQL LIKE . Хоча це не те, на що вам потрібна відповідь, але ви все одно дізнаєтесь про те, як працює індексація під капотом.

* Редагувати: див. Посилання, подані нижче в коментарях, щоб дізнатися більше про індексацію.


8
-1 Індексація кожного стовпця НЕ є найкращою практикою. Кожен індекс коштує вам декількома способами. Переконайтеся, що ви вибрали хороші індекси, які зазвичай складаються з декількох стовпців, як правило, у порядку вибірковості та використовуваної частоти. Це може бути похилий SQL Server, але інформація про індекс все ще діє: sqlskills.com/BLOGS/KIMBERLY/post/… .
Ерік Хамфрі - лоташельп

@Eric Хамфрі +1 Для пояснення та посилання на сайт Кімберлі.
Мт М

ви не праві, що має індекс стовпця іноді боляче продуктивність на деяких запитах: mysqlperformanceblog.com/2007/08/28 / ... . НІКОЛИ не слід застосовувати правило: іноді воно працює, іноді ні.
sumar

Правильно, я згоден. Однак це справедливо в тому випадку, якщо вибірковість значення низька. Зважаючи на тип даних, який використовує Патрік (цей автор запитань), який є DATETIME, рекомендується індексувати. Зазвичай у цього типу поля є досить великий набір значень, якщо тільки немає випадкової ситуації, коли він використовує лише декілька можливих дат. * Я відредагую свою відповідь вище, щоб зробити більш чітким і достовірним твердження.
Очі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.