C, PHP, VB, .NET

Дневникът на Филип Петров


* Индекси

Публикувано на 08 април 2009 в раздел Бази от Данни.

Индексите са обекти в базата данни, които ни осигуряват бърз достъп до редовете на базова таблица, чрез физическото представяне (адреси в паметта) на данните. Индексите се създават върху колони на таблиците.

Присъствието или отсъствието на индекс няма ефект върху крайния резултат на заявките. Единствената разлика е в евентуалното повишено бързодействие (при по-големи таблици може разликата да е огромна). Важно е обаче да създаваме индексите правилно, защото от това зависи дали системата ще ги използва или не.

За да демонстрираме повишеното бързодействие сме изпълнили една проста заявка на доста бавен компютър.:

mysql> SELECT * FROM accounts
    -> WHERE customer_id = 11;
+----+--------+------+-----------+-------------+
| id | amount | type | branch_id | customer_id |
+----+--------+------+-----------+-------------+
| 12 |  99.18 |    1 |         2 |          11 |
+----+--------+------+-----------+-------------+
1 row in set (0.30 sec)

Нека сега създадем индекс по колоната, която участва в условието WHERE на оператора SELECT и изпълним заявката отново:

mysql> CREATE INDEX accounts_customer_id
    -> ON accounts(customer_id);
Query OK, 27 rows affected (1.93 sec)
Records: 27  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM accounts
    -> WHERE customer_id = 11;
+----+--------+------+-----------+-------------+
| id | amount | type | branch_id | customer_id |
+----+--------+------+-----------+-------------+
| 12 |  99.18 |    1 |         2 |          11 |
+----+--------+------+-----------+-------------+
1 row in set (0.03 sec)

Трябва да отбележа, че в този тестов пример колоната customer_id НЕ Е foreign key. Системата за управление на бази данни създава автоматично индекси по първични и външни ключове.

Обикновено за структура от данни на индексите се използва BTREE (бинарно дърво). При различните системи има възможности за използване на алтернативни структури, но това не е задължително.

Истината е, че индексите не винаги са подходящи. В редица случаи те може да навредят на производителността на системата. Това се получава ако имаме таблици, върху които често правим заявки от тип UPDATE, INSERT и DELETE, то всеки път индексът трябва да се обновява. Затова таблици, в които често се добавят данни и рядко се четат такива е по-добре да не използваме индекс.

Същото важи и за индексите върху колони с много повтарящи се редове. Ако имаме такава колона, в която данните се повтарят изключително много, то по-добре да не създаваме индекс, защото ефектът ще бъде на забавяне на системата. Създавайте предимно индекси върху колони с ключ UNIQUE.

Ако вашите таблици се обновяват периодично (например в края на месеца се обновява таблица със статистики), то следвайте следната последователност:
- Изтриване на индекса;
- Обновяване на данните;
- Създаване на индекса отново.

Ето още един пример за създаване и изтриване на индекс:

mysql> CREATE INDEX customers_name
    -> ON customers(name);
Query OK, 22 rows affected (0.17 sec)
Records: 22  Duplicates: 0  Warnings: 0

mysql> DROP INDEX customers_name
    -> ON customers;
Query OK, 22 rows affected (0.15 sec)
Records: 22  Duplicates: 0  Warnings: 0

Можете лесно да се досетите, че е възможно да направите повече от един индекс върху една таблица. В последствие когато правите заявки SELECT MySQL обикновено се досеща кой индекс е най-подходящ при заявката. Въпреки това е възможно вие сами да укажете кой индекс да се използва:

mysql> SELECT * FROM mytable
    -> USE INDEX (col1index, col2index)
    -> WHERE col1 = 1 AND col2 = 2;

Ако пък желаете е възможно да укажете кой индекс да НЕ се използва чрез командата "IGNORE INDEX":

mysql> SELECT * FROM mytable
    -> IGNORE INDEX (col1index)
    -> WHERE col1 = 1 AND col2 = 2;

 



3 коментара


  1. Това е името на индекса. Може да е каквато и да е дума. После се указва чрез "USE INDEX" или "IGNORE INDEX" - ако не, то ще стане по усмотрение на системата.

  2. В примера "mysql> CREATE INDEX accounts_customer_id" не трябва ли да е "accounts.customer_id"?Ако не защо?

  3. Благодаря, вече го разбрах.

Добави коментар

Адресът на електронната поща няма да се публикува


*