2013-11-07 2 views
4

У меня есть 3 таблицы в MySQL:MySQL первичного ключа для того пара влияет РЕГИСТРИРУЙТЕСЬ СКОРОСТЬ

innodb_verion  1.1.8 
version   5.5.29-log 
Table: artist 
Columns: 
    id    int(11) 
    new_id   varchar(50) 
Table: collection 
Columns: 
    id    int(11) 
    new_id   varchar(50) 
Table: artist_collection 
Columns: 
    artist_id  int(11) PK 
    collection_id int(11) PK 

Таблицы художника и коллекция содержит 100 строк (I просто вытащил подмножество для проверки этой проблемы)

Таблица artist_collection содержит 8 миллионов + строк и имеет первичный ключ, созданный как:

ALTER TABLE artist_collection ADD PRIMARY KEY (artist_id,collection_id); 

Когда я тождественны присоединяется к художнику и коллекции, коллекция занимает значительно больше времени, чем художник:

SELECT artist.new_id AS 'i' FROM artist INNER JOIN artist_collection ON artist.id=artist_collection.artist_id LIMIT 100; 
100 row(s) returned 0.001 sec 
SELECT collection.new_id AS 'i' FROM collection INNER JOIN artist_collection ON collection.id=artist_collection.collection_id LIMIT 100; 
100 row(s) returned 2.636 sec 

Это большое дело, потому что эти исходные таблицы составляют 10 миллионов + строк, и я не хочу использовать LIMIT в моих запросах. Даже когда я сделал LIMIT 1000, медленный запрос займет ~ 35 секунд, тогда как быстрый был ~ 0,020 секунд. Я тогда ОБЪЯСНИТЬ РАСПРОСТРАНЕНИЯ на обоих запросов, чтобы посмотреть, что происходит на самом деле:

EXPLAIN EXTENDED SELECT artist.id AS 'i' FROM artist INNER JOIN artist_collection ON artist.id=artist_collection.artist_id LIMIT 100; 

id select_type table    type possible_keys key  key_len ref    rows filtered Extra 
1  SIMPLE   artist    ALL  NULL    NULL  NULL  NULL    82  100.00 
1  SIMPLE   artist_collection ref  PRIMARY   PRIMARY 4   tbl.artist.id 2  100.00  Using index 
EXPLAIN EXTENDED SELECT collection.id AS 'i' FROM collection INNER JOIN artist_collection ON collection.id=artist_collection.collection_id LIMIT 100; 

id select_type table    type possible_keys key  key_len ref  rows  filtered Extra 
1  SIMPLE   collection   ALL  NULL    NULL  NULL  NULL  101  100.00 
1  SIMPLE   artist_collection index NULL    PRIMARY 8   NULL  8725465 100.00  Using where; Using index; Using join buffer 

Как вы можете видеть, это не обрабатывает запросы одинаково. Затем я побежал:

ALTER TABLE artist_collection DROP PRIMARY KEY; 
ALTER TABLE artist_collection ADD PRIMARY KEY (collection_id,artist_id); 

Это вызвало проблему переломить себя, где сейчас художник РЕГИСТРИРУЙТЕСЬ принимает очень долго. Поэтому мои вопросы таковы:

1) Разве MySQL интерпретирует первую и вторую записи PRIMARY KEY по-разному?
2) Что именно происходит?
3) Как сделать запросы одинаковыми (быстрыми)?

ответ

1

Подумайте о записях в этом соединение индекса, хранящегося таким образом:

+---------------+-----------+ 
| collection_id | artist_id | 
+---------------+-----------+ 
|    1 |   1 | 
|    1 |   2 | 
|    1 |   3 | 
|    2 |   1 | 
|    2 |   2 | 
|    3 |   1 | 
+---------------+-----------+ 

Учитывая тот факт, что данные сначала сортируются по collection_id ищет все collection_id = 1 очень просто. Тем не менее, для всех artist_id нет.

Даже если вы ищете как collection_id = 1 and artist_id = 1, тогда это также легкая задача (вам не нужно сканировать все значения artist_id).

Аналогичная вещь происходит с MySQL. Когда вы присоединяетесь только к collection_id, этот показатель очень полезен. Когда вы присоединяетесь как collection_id, так и artist_id, этот показатель снова полезен. Однако при присоединении только к artist_id этот показатель не поможет.

Если вы собираетесь присоединиться к группе только по адресу artist_id, то можете добавить еще один индекс на artist_id.Вы должны увидеть в своем exaplain, что новый индекс будет использоваться в этих запросах.

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