Як додати індекси до таблиць MySQL?


407

У мене дуже велика таблиця MySQL з приблизно 150 000 рядками даних. В даний час, коли я пробую і бігаю

SELECT * FROM table WHERE id = '1';

код працює нормально, оскільки поле ID є основним індексом. Однак для недавньої розробки проекту мені доведеться шукати в базі даних за іншим полем. Наприклад:

SELECT * FROM table WHERE product_id = '1';

Це поле раніше не було індексовано; Однак я додав його, тому mysql тепер індексує поле, але коли я намагаюся запустити вищезазначений запит, він працює дуже повільно. Запит EXPLAIN виявляє, що не існує індексу для поля product_id, коли я вже додав його, і в результаті запит займає десь від 20 хвилин до 30 хвилин, щоб повернути один рядок.

Мої повні ПОЯСНЕННІ результати:

| id | select_type | table | type | possible_keys| key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+--------------+------+---------+------+-------+------------------+
|  1 | SIMPLE      | table | ALL  | NULL         | NULL | NULL    | NULL |157211 | Using where |
+----+-------------+-------+------+--------------+------+---------+------+-------+------------------+

Можливо, буде корисно зазначити, що я щойно подивився, а поле ідентифікатора зберігається як INT, тоді як поле PRODUCT_ID зберігається як VARCHAR. Чи може це бути джерелом проблеми?


1
Чи можете ви опублікувати всі EXPLAINрезультати? Ви впевнені, що індексу немає ? Або індекс є, але MySQL вирішив не використовувати його?
— VoteyDisciple

169
Великий стіл мав би 150 000 000 записів. Дуже велика таблиця має 15 000 000 000 записів. Таблиця середнього розміру має 150 000. Для подальшого ознайомлення.
— usumoio

4
Майте на увазі, що "АБО" може змусити MySql не використовувати індекси. У мене був запит із 3 АБО. Кожен пішов на індекс і пробіг за 15 мс, Усі разом взяли між 25 сек і таймаутом. Тому я зробив 3 запити, і UNION'ed їх разом, це також зайняло 15 мс на 500 000 рядків.
— Лейф Неланд

Розглянемо тип даних, який ви зберігаєте. Ефективність може змінюватися залежно від типу даних, який ви порівнюєте. Як ви сказали, що PRODUCT_ID - це тип даних VARCHAR, спробуйте змінити його на INT та індексувати стовпець.
— gilbertdim

Відповіді:


606
ALTER TABLE `table` ADD INDEX `product_id_index` (`product_id`)

Ніколи не порівнюйте integerз stringsMySQL. Якщо idє int, видаліть цитати.


Я вже додав індекс за допомогою саме цього SQL, але здається, що він не "застосований" до даних, і запит EXPLAIN показує, що для цього поля немає індексу.
— Майкл

1
Потрібно перевірити індекс за допомогою SHOW CREATE TABLE, чи це ви вже зробили?
— Wrikken

33
Використовуйте SHOW INDEXES FROM YOURTABLE dev.mysql.com/doc/refman/5.0/uk/show-index.html, щоб перевірити, чи додані індекси
— Тимо Хуовінен

6
Сьогодні у мене була точна проблема, яку @Michael описує, і рішенням було "Ніколи не порівнюйте цілі числа з рядками в mysql." Дякую.
— користувач12345

@Wrikken Я додав свій індекс і використав вашу команду ПОКАЗУЙТЕ ІНДЕКСИ З ВАШОГО. Він відображається, але я не думаю, що він використовується, коли я запитую свій стіл. Чи потрібно змінювати запит вибору при використанні індексу?
— Ced

147
ALTER TABLE TABLE_NAME ADD INDEX (COLUMN_NAME);

96
В MySQL, якщо використовувати ALTER TABLE tbl ADD INDEX (col)замість ALTER TABLE tbl ADD INDEX col (col), а потім з допомогою ALTER TABLE tbl ADD INDEX (col)більш ніж один раз буде продовжувати додавати індекси з іменами col_2, col_3... кожен раз. В той ALTER TABLE tbl ADD INDEX col (col)час як, використовуючи другий раз, дамо ERROR 1061 (42000): Duplicate key name 'col'.
— Абхішек Оза

82

Ви можете використовувати цей синтаксис, щоб додати індекс і керувати видом індексу (HASH або BTREE).

create index your_index_name on your_table_name(your_column_name) using HASH;
or
create index your_index_name on your_table_name(your_column_name) using BTREE;

Дізнатися про відмінності між індексами BTREE та HASH можна тут: http://dev.mysql.com/doc/refman/5.5/uk/index-btree-hash.html


1
Хеш перетворюється на btree, коли я бачу, як використовують покажчики показів.
— RN Kushwaha

1
Що буде за замовчуванням у Hash та BTree, якщо я не вказую жодного?
— Бхавук Матур

2
@ RNKushwaha, тому що InnoDB і MyIsam не підтримують HASH, AFAIK, підтримують його лише двигуни пам’яті пам’яті та NDB
— Hieu Vo

60

Варто відзначити, що кілька індексів поля можуть різко покращити ефективність вашого запиту. Отже, у наведеному вище прикладі ми припускаємо, що ProductID є єдиним полем для пошуку, але запит сказав ProductID = 1 І категорія = 7, то допомагає множина індексу стовпців. Це досягається за допомогою наступного:

ALTER TABLE `table` ADD INDEX `index_name` (`col1`,`col2`)

Крім того, індекс повинен відповідати порядку порядку запитів. У моєму розширеному прикладі індекс повинен бути (ProductID, Category), а не навпаки.


1
Приємно, явне іменування індексу дозволяє легко перевернути.
— Сем Беррі

Чи можете ви цитувати джерело the index should match the order of the query fields?
— Bishwas Mishra

58

Можуть бути додані індекси двох типів: коли ви визначаєте первинний ключ, MySQL прийме його як індекс за замовчуванням.

Пояснення

Первинний ключ як індекс

Подумайте, у вас є tbl_studentтаблиця, і ви хочете student_idв якості основного ключа:

ALTER TABLE `tbl_student` ADD PRIMARY KEY (`student_id`)

Вищенаведене твердження додає первинний ключ, а це означає, що індексовані значення повинні бути унікальними і не можуть бути NULL.

Вкажіть ім'я індексу

ALTER TABLE `tbl_student` ADD INDEX student_index (`student_id`)

Наведене вище твердження створить звичайний індекс з student_indexім'ям.

Створіть унікальний індекс

ALTER TABLE `tbl_student` ADD UNIQUE student_unique_index (`student_id`)

Тут student_unique_indexім’я індексу присвоюється student_id та створює індекс, значення якого повинно бути унікальним (тут нуль можна прийняти).

Варіант повного тексту

ALTER TABLE `tbl_student` ADD FULLTEXT student_fulltext_index (`student_id`)

Вищенаведене твердження створить ім'я індексу Fulltext student_fulltext_index, за допомогою якого вам потрібен MyISAM Mysql Engine.

Як видалити індекси?

DROP INDEX `student_index` ON `tbl_student`

Як перевірити наявні індекси?

SHOW INDEX FROM `tbl_student`

17

Ви кажете, що маєте індекс, пояснення говорить інакше. Однак якщо це дійсно так, продовжувати:

Якщо у вас стовпчик індексу, і MySQL вирішує не використовувати його, він може:

  1. У запиті MySQL є ще один індекс, який вважається більш доцільним у використанні, і він може використовувати лише один. Рішення зазвичай є індексом, що охоплює декілька стовпців, якщо їх звичайний спосіб пошуку є значенням більше одного стовпця.
  2. MySQL вирішує, що існує багато відповідних рядків, і вважає, що таблицяможе швидше. Якщо це не так, іноді ANALYZE TABLEдопомагає.
  3. У більш складних запитах він вирішує не використовувати його на основі надзвичайно розумного продуманого вуду в плані запитів, який чомусь просто не відповідає вашим поточним вимогам.

У випадку (2) або (3) ви можете змусити MySQL використовувати індекс за допомогою індексу підказки sytax , але якщо ви це зробите, не забудьте виконати деякі тести, щоб визначити, чи дійсно це покращує продуктивність, щоб використовувати індекс, як ви натякаєте на нього .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.