MySQL连接表,分区选择所有分区

MySQL连接表,分区选择所有分区,mysql,database-partitioning,Mysql,Database Partitioning,我的网站上有一个照片库,里面有100万张照片。有2个与之关联的搜索表。表1列出了照片中使用的单词。表2列出了哪些单词与哪些照片相匹配。表2为7M行。我正在测试对这个7M行表进行分区,因为我还有一组120000000行的表。对下面120M行wordmatch表的查询,无论是否与下面的wordlist表连接,都需要几秒钟的时间运行 我试图在这两个表之间执行连接,MySQL 5.6解释分区显示它正在使用所有分区。如何重做此查询以使其仅正确使用单个分区 两个表: CREATE TABLE wordlis

我的网站上有一个照片库,里面有100万张照片。有2个与之关联的搜索表。表1列出了照片中使用的单词。表2列出了哪些单词与哪些照片相匹配。表2为7M行。我正在测试对这个7M行表进行分区,因为我还有一组120000000行的表。对下面120M行wordmatch表的查询,无论是否与下面的wordlist表连接,都需要几秒钟的时间运行

我试图在这两个表之间执行连接,MySQL 5.6解释分区显示它正在使用所有分区。如何重做此查询以使其仅正确使用单个分区

两个表:

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 |
+----+-------------+-------+-----------------------------------+-------+-----------------+---------+---------+----------------------------+------+-------------+
联接生成一个使用所有分区的查询。 如果我首先检索单词_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 |
+----+-------------+-------+------------+------+---------------+---------+---------+-------+-------+-------------+
我如何让它正常工作? 如果可能的话,我不希望将其拆分为多个查询。 您可能已经注意到我正在使用上面的方法。人们通常会搜索bacon%以获得单词的复数形式,等等。 例如:

我意识到这种通配符搜索可能会导致选择2个或更多分区。这可能没问题,不过如果有办法更改分区以防止出现这种情况,我欢迎提供任何提示

编辑#1:添加了详细信息,因为我原来的问题令人困惑。在做120米行表格之前,我先测试了7米行表格


编辑#2:解决我的整体问题:我的性能问题似乎得到了解决,因为我在每篇文章中将我的120M行表划分为101个分区:我不知道MySQL在运行时是否会与所有分区相冲突-Ollie Jones在下面的评论中说不会,并解释分区是不正确的-但事实确实如此现在快了,所以我很高兴。

您的第一个查询在
wordmatch
表上没有任何可能限制正在使用的分区的过滤条件,因此它需要访问所有分区。如果不在作为分区基础的字段上添加筛选器(
word\u id
),则无法重新执行此查询以仅使用必要的分区

第二个查询过滤特定的
word\u id
值,因此索引确切地知道要指向哪个分区


我也同意@OllieJones的评论,我不确定您是否真的应该担心只有700万行的分区。在事物的大模式中,这实际上并不是一个很大的表。

在开始分区项目之前,让查询使用有效的索引可能是一个好主意。以下是经过重构以使用
JOIN
的查询:

SELECT m.pic_id 
  FROM wordlist w
  JOIN wordmatch m ON w.word_id = m.word_id
 WHERE w.word_text LIKE 'bacon%' 
此查询可以在
单词列表(单词测试,单词id)
上使用复合索引。它将随机访问第一个匹配的
word\u文本的索引
,然后扫描检索
word\u id
值的索引,直到找到最后一个匹配的`word\u文本

它还可以在
wordmatch(word\u id,pic\u id)
上使用您现有的主键。它可以加快您的查询速度,因为数据库引擎可以直接从索引满足您的查询,而无需将硬盘驱动器来回切换到表本身

所以,尝试一下这些索引。您的大表
wordmatch
表在没有分区的情况下应该可以很好地工作。对包含大量内容(如文章文本)的表进行分区比对这种固定行大小的联接表进行分区更常见

请注意,您的
EXPLAIN
宣布它将查看所有分区,因为
EXPLAIN
无法区分您的
w.word\u文本(如“bacon%”)
WHERE子句)需要检查哪些分区<代码>解释不像一盒锤子那么愚蠢,但它很接近。MySQL不会检查不需要检查的分区,但在运行时之前它不知道涉及哪些分区


你考虑过使用全文搜索吗?这可能会简化你的工作

请注意:我认为7兆行的大小不足以证明您所描述的表的分区是合理的。如果对表进行分区,则或多或少会带来永久性的系统管理员负担和查询开销负担。我建议您花点精力为
wordmatch
表编制索引,谢谢。我将更改或添加哪些索引?我应该提到,在我对另一个有1.2亿行的表做同样的测试之前,我实际上是在使用这个表作为测试。哇,所以查询执行计划器不知道要查找wordlist.word\u id,首先要知道wordmatch.word\u id要使用哪个分区。所以唯一的解决方案是将其拆分为多个查询,对的在对wordmatch包含1.2亿行的另一组表执行相同操作之前,我将对这组表进行测试。我将编辑原始帖子。在从7M表中检索记录时,有时会出现一些延迟,可能与大小无关。我可以运行一个查询,第一个查询需要7-8秒,但下一个查询需要0.008秒,就像它必须加载到内存或以某种方式升级一样?我将9GB分配给INNODB,其中INNODB表总计为7G,因此这不应该是内存问题。欢迎任何建议。@63bus在计划阶段,计划员还不知道哪个单词id与
w.word\u text
的条件匹配,因此不知道需要哪些分区。@63bus这可能与您的搜索条件有关。如果您使用像“培根”这样的
(实际上与
=“bacon”
)或像“bacon%”这样的
则可以使用
word\u text
上的索引。如果像“%bacon%”那样使用
则由于索引匹配星号,因此将无法使用索引
SELECT m.pic_id 
  FROM wordlist w
  JOIN wordmatch m ON w.word_id = m.word_id
 WHERE w.word_text LIKE 'bacon%'