2016-02-12 2 views
3

Это структура таблицы:Какой индекс должен повысить производительность выбранного запроса?

+--------------+--------------+------+-----+---------+----------------+ 
| Field  | Type   | Null | Key | Default | Extra   | 
+--------------+--------------+------+-----+---------+----------------+ 
| id   | int(11)  | NO | PRI | NULL | auto_increment | 
| visitor_hash | varchar(40) | YES | MUL | NULL |    | 
| uri   | varchar(255) | YES |  | NULL |    | 
| ip_address | char(15)  | YES | MUL | NULL |    | 
| last_visit | datetime  | YES |  | NULL |    | 
| visits  | int(11)  | NO |  | NULL |    | 
| object_app | varchar(255) | YES | MUL | NULL |    | 
| object_model | varchar(255) | YES |  | NULL |    | 
| object_id | varchar(255) | YES |  | NULL |    | 
| blocked  | tinyint(1) | NO |  | NULL |    | 
+--------------+--------------+------+-----+---------+----------------+ 

Это запрос:

SELECT `object_id` 
    FROM `visits_visit` 
    WHERE `object_model` = 'News' 
    GROUP BY `object_id` 
    ORDER BY COUNT(*) DESC 
    LIMIT 0, 3 

Время реакции составляет ~ 77,63 мс.

CREATE INDEX resource_model ON visits_visit (object_model(100)); 

После этого запроса время ответа увеличилось до ~ 150 мс.

Как улучшить производительность для этого случая? Спасибо.

ОБНОВЛЕНО:

Отвечая на Михала Коморовского. Это объясняет, прежде чем индекс:

+----+-------------+--------------+------+---------------+------+---------+------+--------+----------------------------------------------+ 
| id | select_type | table  | type | possible_keys | key | key_len | ref | rows | Extra          | 
+----+-------------+--------------+------+---------------+------+---------+------+--------+----------------------------------------------+ 
| 1 | SIMPLE  | visits_visit | ALL | NULL   | NULL | NULL | NULL | 142938 | Using where; Using temporary; Using filesort | 
+----+-------------+--------------+------+---------------+------+---------+------+--------+----------------------------------------------+ 
1 row in set (0.00 sec) 

И это после того, как индекс:

+----+-------------+--------------+------+----------------+----------------+---------+-------+-------+----------------------------------------------+ 
| id | select_type | table  | type | possible_keys | key   | key_len | ref | rows | Extra          | 
+----+-------------+--------------+------+----------------+----------------+---------+-------+-------+----------------------------------------------+ 
| 1 | SIMPLE  | visits_visit | ref | resource_model | resource_model | 303  | const | 64959 | Using where; Using temporary; Using filesort | 
+----+-------------+--------------+------+----------------+----------------+---------+-------+-------+----------------------------------------------+ 
1 row in set (0.00 sec) 

Я не знаю, что дает мне эту информацию.

SELECT `object_id` 
    FROM `visits_visit` 
    WHERE `object_model` = 'News' 
    GROUP BY `object_id` 
    ORDER BY COUNT(*) DESC 
    LIMIT 0, 3 

78,85 мс до индексации и 365,59 мс после индексирования.

Также у меня есть индекс

CREATE INDEX resource ON visits_visit (object_app(100), object_model(100), object_id(100)); 

Но мне нужно это одно, потому что в других запросах на выборку WHERE содержит эти три ключа.

UPDATE:

Я использую Джанго панель инструментов отладки для тестирования производительности запросов.

ОБНОВЛЕНИЕ:

Запрос:

ANALYZE TABLE visits_visit; 

Выход:

+-----------------------------+---------+----------+-----------------------------+ 
| Table      | Op  | Msg_type | Msg_text     | 
+-----------------------------+---------+----------+-----------------------------+ 
| **************.visits_visit | analyze | status | Table is already up to date | 
+-----------------------------+---------+----------+-----------------------------+ 
1 row in set (0.00 sec) 

ОБНОВЛЕНИЕ:

SHOW INDEXES FROM visits_visit; 

Выход:

+--------------+------------+-----------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| Table  | Non_unique | Key_name    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
+--------------+------------+-----------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| visits_visit |   0 | PRIMARY    |   1 | id   | A   |  142938 |  NULL | NULL |  | BTREE  |   |    | 
| visits_visit |   1 | visits_visit_0880babc |   1 | visitor_hash | A   |  142938 |  NULL | NULL | YES | BTREE  |   |    | 
| visits_visit |   1 | visits_visit_5325a746 |   1 | ip_address | A   |  142938 |  NULL | NULL | YES | BTREE  |   |    | 
| visits_visit |   1 | resource    |   1 | object_app | A   |   1 |  100 | NULL | YES | BTREE  |   |    | 
| visits_visit |   1 | resource    |   2 | object_model | A   |   3 |  100 | NULL | YES | BTREE  |   |    | 
| visits_visit |   1 | resource    |   3 | object_id | A   |   959 |  100 | NULL | YES | BTREE  |   |    | 
+--------------+------------+-----------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
+0

Вы проверили план выполнения до и после применения индекса? –

+0

Спасибо за ответ, Михал Коморовский, я ответил вам ниже. – vadimka

+0

Sandy, количество строк меньше, чем во втором случае, но второе тратит больше времени на ответ. Я не понимаю, почему. – vadimka

ответ

0

Я растерялась непониманием механизмов SQL, поэтому я решил создать модель Популярная и сохранить экземпляры в нем каждые 24 часа. Спасибо всем, кто пытался помочь.

+0

Просто проверьте количество строк, проверенных до и после создания индекса. – Sandy

+0

Благодарим вас за ответ, Сэнди, что значит проверить? – vadimka

+0

Столбец строк указывает количество строк, которые MySQL считает необходимым для выполнения запроса. https://dev.mysql.com/doc/refman/5.5/en/explain-output.html – Sandy

0

Мне кажется, что хотя у вас есть индекс, MySQL не знает, как правильно его использовать. Это происходит, когда информация о распределении данных (статистика) в таблице не обновляется. Чтобы их обновить, вы должны позвонить ANALYZE TABLE visits_visit, а затем проверить результаты.

+0

Я сделал это и добавил к вопросу. – vadimka

0

Как я уже сказал в вашем другом вопросе, индексы Префикса практически бесполезны; не используйте их, за исключением редких случаев.

Сократите поля до разумной длины, и вы не захотите использовать префиксные индексы.

Оптимальным индексом для этого запроса является INDEX(object_model, object_id). Попытка использовать INDEX(object_model(##), ...) не пройдет object_model никому после этого.

Если object_model такие вещи, как «Новости», я подозреваю, что другие возможные значения короткие, и, возможно, существует конечное число моделей. Для «коротких» изменений на несколько меньших VARCHAR. Для «конечных» рассмотрите использование ENUM('News', 'Weather', 'Sports', ...).

А почему это заняло больше времени после индексации ...

  • Без индекса, оптимизатор не было выбора, кроме как сканировать всю таблицу. Это простое линейное сканирование. Он будет читать, но не считать любые строки без новостей.
  • С индексом Оптимизатор имеет дополнительный выбор использования индекса. Но, может быть, большинство строк - Новости? Ну, он сканирует индекс (хороший), но для каждого пункта новостей в индексе ему придется искать строку, чтобы получить object_id (не так приятно). Кажется (из таймингов), что последний менее эффективен.

Сокращая декларации и используя INDEX(object_model, object_id) (в этом порядке), запрос может быть выполнен в индексе. Подумайте об индексе как мини-таблице с этими двумя столбцами. Он меньше. Он упорядочен по модели, поэтому ему нужно только отсканировать часть «Новости». Объяснение покажет это «покрытие», сказав «Использование индекса».

Если все случаи, GROUP BY добавляет некоторые накладные расходы - либо сохраняя хэш object_id в ОЗУ, либо сохраняя промежуточные результаты и сортируя их. Затем ORDER BY требует сортировки (или хэша приоритета) до того, как может применяться LIMIT.

Смежные вопросы