4

我在 MySQL 中有 3 个表:

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 行(我只是抽出一个子集来测试这个问题)

Artist_collection 表包含超过 800 万行,并有一个 PRIMARY KEY 创建为:

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

这很重要,因为这些原始表有 1000 万多行,我不想在查询中使用 LIMIT。即使我做了 LIMIT 1000,慢速查询也需要大约 35 秒才能完成,而快速查询大约需要 0.020 秒。然后我对两个查询都做了一个 EXPLAIN EXTENDED 来看看到底发生了什么:

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);

这导致问题自行逆转,现在艺术家 JOIN 需要很长时间。所以我的问题是这样的:

1) MySQL 是否以不同的方式解释 PRIMARY KEY 的第一个和第二个条目?
2)到底发生了什么?
3)如何使查询相等(快速)?

4

1 回答 1

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_idartist_id此索引再次有用。但是,仅在artist_id此索引上加入时不会有太大帮助。

如果您还打算只加入,artist_id那么您可能需要在artist_id. 您应该exaplain在这些查询中看到将使用新索引。

于 2013-11-07T18:06:53.650 回答