【发布时间】:2014-11-04 18:37:59
【问题描述】:
我的网站上有一个照片库,里面有 100 万张照片。有 2 个与之关联的搜索表。表 #1 包含照片中使用的单词列表。表 #2 包含哪些单词与哪些照片匹配的列表。表 #2 是 7M 行。我正在测试对这个 7M 行表进行分区,因为我有另一组包含 120,000,000 行的表。查询下面的 120M 行 wordmatch 表,无论是否再次连接下面的 wordlist 表,都需要几秒钟才能运行。
我正在尝试在这 2 个表之间执行连接,并且 MySQL 5.6 EXPLAIN PARTITIONS 显示它正在使用所有分区。如何重做此查询以使其正确使用仅一个分区?
两张桌子:
CREATE TABLE wordlist (
word_text varchar(50) NOT NULL DEFAULT '',
word_id mediumint(8) unsigned NOT NULL AUTO_INCREMENT
PRIMARY KEY (word_text),
KEY word_id (word_id)
) ENGINE=InnoDB
CREATE TABLE wordmatch (
pic_id int(11) unsigned NOT NULL DEFAULT '0',
word_id mediumint(8) unsigned NOT NULL DEFAULT '0',
title_match tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (word_id,pic_id,title_match),
KEY pic_id (pic_id)
) ENGINE=InnoDB
/*!50100 PARTITION BY HASH (word_id)
PARTITIONS 11 */;
我正在执行的 SQL 查询:
EXPLAIN PARTITIONS SELECT m.pic_id FROM wordlist w, wordmatch m WHERE w.word_text LIKE 'bacon' AND m.word_id = w.word_id
+----+-------------+-------+-----------------------------------+-------+-----------------+---------+---------+----------------------------+------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-----------------------------------+-------+-----------------+---------+---------+----------------------------+------+-------------+
| 1 | SIMPLE | w | NULL | range | PRIMARY,word_id | PRIMARY | 52 | NULL | 1 | Using where |
| 1 | SIMPLE | m | p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10 | ref | PRIMARY | PRIMARY | 3 | w.word_id | 34 | Using index |
+----+-------------+-------+-----------------------------------+-------+-----------------+---------+---------+----------------------------+------+-------------+
连接产生一个使用所有分区的查询。 如果我先检索 word_id # 并直接对照 wordmatch 表,一切正常:
EXPLAIN PARTITIONS SELECT m.pic_id FROM wordmatch m WHERE m.word_id = 219657;
+----+-------------+-------+------------+------+---------------+---------+---------+-------+-------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------------+------+---------------+---------+---------+-------+-------+-------------+
| 1 | SIMPLE | m | p9 | ref | PRIMARY | PRIMARY | 3 | const | 18220 | Using index |
+----+-------------+-------+------------+------+---------------+---------+---------+-------+-------+-------------+
如何让它正常工作? 如果可能,我不希望将其拆分为多个查询。 您可能已经注意到我在上面使用了 LIKE。人们经常会搜索 bacon% 以获取单词的复数等。 示例:
SELECT m.pic_id FROM wordlist w, wordmatch m WHERE w.word_text LIKE 'bacon%' AND m.word_id = w.word_id
我意识到这种通配符搜索可能会导致选择 2 个或更多分区。这可能没问题,但如果有办法更改分区以防止这种情况发生,我欢迎任何提示。
编辑 #1: 添加了详细信息,因为我最初的问题令人困惑。在做我的 120M 行表之前,我先测试了我的 7M 行表。
编辑#2:解决我的整体问题:我的性能问题似乎得到了解决,因为我根据这篇文章将我的 120M 行表划分为 101 个分区:MySQL performance: partitions我不知道 MySQL 是否在运行时反对所有分区 - Ollie Jones 说它不在下面的 cmets 中并且 EXPLAIN PARTITIONS 不正确 - 但现在它很快,所以我很高兴。
【问题讨论】:
-
只是一个评论:我相信七兆行不足以证明对您描述的表进行分区是合理的。如果对表进行分区,您将承担或多或少的永久系统管理员负担和查询开销负担。我可以建议您花精力为
wordmatch表编制索引吗? -
谢谢。我会更改或添加哪些索引?我应该提到,在我对另一个有 1.2 亿行的表做同样的事情之前,我实际上是在使用这个表作为测试。
标签: mysql database-partitioning