2016-12-16 3 views
0

Я пытаюсь создать дополнительный индекс или индексы, чтобы ускорить запрос ниже. Все ключи являются первичными ключами (за исключением идентификатора в таблице A), поэтому они уже имеют связанный с ними индекс btree по умолчанию. id в таблице A также имеет индекс, уже связанный с ним, поскольку его ключ MUL означает, что он является частью уникального индекса.SQL - Составной индекс на внутренней таблице соединений?

Select A.id 
From TableA A 
     Inner join TableB B 
     On A.address = B.address 
     And A.code = B.code 
Group by A.id 
Having count(distinct B.user) = 1; 

Это текущий индекс на вышеуказанных таблицах:

mysql> show index from TableA; 
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| TableA |   0 | PRIMARY |   1 | address  | A   |   8 |  NULL | NULL |  | BTREE  |   | 
| TableA |   0 | PRIMARY |   2 | code   | A   |   24 |  NULL | NULL |  | BTREE  |   | 
| TableA |   1 | id  |   1 | id   | A   |   8 |  NULL | NULL |  | BTREE  |   | 
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 


mysql> show index from TableB; 
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| TableB |   0 | PRIMARY |   1 | user  | A   |   9 |  NULL | NULL |  | BTREE  |   | 
| TableB |   0 | PRIMARY |   2 | address  | A   |   9 |  NULL | NULL |  | BTREE  |   | 
| TableB |   0 | PRIMARY |   3 | code  | A   |   9 |  NULL | NULL |  | BTREE  |   | 
| TableB |   1 | address |   1 | address  | A   |   9 |  NULL | NULL |  | BTREE  |   | 
| TableB |   1 | address |   2 | code  | A   |   9 |  NULL | NULL |  | BTREE  |   | 
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 

Запрос объяснить штатам это:

+----+-------------+-------+--------+---------------+---------+---------+---------------------------------------+------+----------------------------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref         | rows | Extra          | 
+----+-------------+-------+--------+---------------+---------+---------+---------------------------------------+------+----------------------------------------------+ 
| 1 | SIMPLE  | F  | index | address  | address | 514  | NULL         | 9 | Using index; Using temporary; Using filesort | 
| 1 | SIMPLE  | A  | eq_ref | PRIMARY  | PRIMARY | 514  | db.B.address,db.B.code    | 1 |            | 
+----+-------------+-------+--------+---------------+---------+---------+---------------------------------------+------+----------------------------------------------+ 

У меня возникли проблемы с пониманием того, что я должен делать. Является ли составной индекс адреса и кода единственным, что я мог бы сделать, чтобы улучшить скорость упомянутого запроса?

Или представляет собой кластерный индекс id (поскольку запрос использует группу by) лучше? Или я мог бы использовать оба?

+0

Я думаю, что * сгруппированный индекс * вы можете означать * составной индекс *. Кластеризованные индексы - это вещи на SQL-сервере, но не в MySQL. –

+0

'ПЕРВИЧНЫЙ КЛЮЧ (адрес, код)' является как «композитным» (aka «составным»), так и сгруппированным. В InnoDB PK по определению MySQL уникален и сгруппирован. –

+1

Это дубликат http://dba.stackexchange.com/questions/158385/compound-index-on-inner-join-table, который имеет один ответ до сих пор. –

ответ

2

По состоянию на конец 2016 года MySQL не может использовать более одного индекса для любой данной таблицы в одном запросе. Таким образом, добавление новых индексов с одним столбцом не помогает. Думаю, ты это знаешь.

Трудно понять, насколько хорошо будет работать составной индекс, не пытаясь его выполнить. При этом я предлагаю вам попробовать этот индекс на TableB. (address, code, user)?

Почему? Запрос ищет конкретные значения code и address, затем суммирует user. Попробуйте.

Вы также можете попробовать составной индекс на TableA. Это будет (id, address, code). Это начинается с id, потому что у вас нет никаких WHERE фильтров на TableA, а ваше предложение GROUP BY может быть оптимизировано путем сканирования вашей таблицы в id. Но сначала попробуйте индекс TableB.

http://use-the-index-luke.com/ является хорошей ссылкой.

+0

Спасибо за предложение, на самом деле я относительно новичок в базах данных, и концепции по-прежнему трудно понять на данный момент. – spacing

+0

Поскольку у меня есть группа по инструкции, не рекомендуется ли иметь кластерный индекс для id в таблице A? – spacing

+0

В качестве альтернативы, перестройте свой ПК, поставив 'user' последним. –

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