我有以下表格:test_user
,test_tag
,product
,productinfo
(productinfo
有product
的外键。
此外,我还有一些表格可以模拟以前表格之间的某些关系:test_usertagging
(FK到test_tag
和test_user
),productinfo_tags
(FK到{{ 1}}和test_tag
)。
(下面我附上一个更全面的描述,但这是主要的想法)。
现在我有一个产品ID和用户ID列表,我希望找到它们之间的共同标记,以及来自test_productinfo
的其他extra_info
列:
test_usertagging
格式化查询:
mysql> explain SELECT `test_usertagging`.`user_id`, `test_usertagging`.`tag_id`, `test_usertagging`.`extra_info`
FROM `productinfo`
INNER JOIN `productinfo_tags` ON ( `productinfo_tags`.`productinfo_id` = `productinfo`.`id` )
INNER JOIN `test_tag` ON ( `test_tag`.`id` = `productinfo_tags`.`tag_id` )
INNER JOIN `test_usertagging` ON ( `test_usertagging`.`tag_id` = `test_tag`.`id` )
WHERE
(`test_usertagging`.`user_id` IN (1,2,3,4 ... ) AND
`productinfo`.`product_id` IN ('abc', 'def', '000', '111', ...));
我得到的是:
SELECT test_usertagging.user_id,
test_usertagging.tag_id,
test_usertagging.extra_info
FROM productinfo
JOIN productinfo_tags ON productinfo_tags.productinfo_id = productinfo.id
JOIN test_tag ON test_tag.id = productinfo_tags.tag_id
JOIN test_usertagging ON test_usertagging.tag_id = test_tag.id
WHERE test_usertagging.user_id IN (1,2,3,4 ... )
AND productinfo.product_id IN ('abc', 'def', '000', '111', ...)
此查询执行得很糟糕。困扰我的是“使用何处”。 (没有索引)最后一行(test_usertagging) - 正确的索引列在+----+-------------+------------------+--------+------------------------------------------------------------------+------------------------------+---------+--------------------------------------+------+--- -----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------------+--------+------------------------------------------------------------------+------------------------------+---------+--------------------------------------+------+--- -----------------------+
| 1 | SIMPLE | productinfo | range | PRIMARY,productinfo_218f3960 | productinfo_218f3960 | 62 | NULL | 55 | Using where; Using index |
| 1 | SIMPLE | productinfo_tags | ref | productinfo_id,productinfo_tags_4b5946a2,productinfo_tags_5659cca2 | productinfo_id | 4 | tookyo_prod.productinfo.id | 1 | Using index |
| 1 | SIMPLE | test_tag | eq_ref | PRIMARY | PRIMARY | 4 | tookyo_prod.productinfo_tags.tag_id | 1 | Using index |
| 1 | SIMPLE | test_usertagging | ref | test_usertagging_5659cca2 | test_usertagging_5659cca2 | 4 | tookyo_prod.productinfo_tags.tag_id | 217 | Using where |
+----+-------------+---------------------+--------+------------------------------------------------------------------+------------------------------+---------+--------------------------------------+------+--------------------------+
下,但它仍然说''使用where'。
我尝试添加key
,但这并没有改善问题(因为无论如何都列出了正确的索引)。
使用FORCE INDEX
只会更改最后两行之间的顺序。 (请注意,STRAIGHT JOIN
表本身对于此查询来说是多余的;将其删除并不会改变任何内容。
有关如何从test_tag
进行查询的任何想法都使用其中一个或两个相关的可用索引(test_usertagging
或user_id
)?
这里是连接表的tag_id
输出:
SHOW CREATE TABLE
答案 0 :(得分:0)
在典型的多对多映射表中,例如test_usertagging
和productinfo_tags
,通常不需要id AUTO_INCREMENT PRIMARY KEY
。删除列,并将复合UNIQUE
键提升为PRIMARY KEY
。
这种改变可能会加快一个方向,因为通过PK进行查找的速度大约是通过辅助密钥进行查找的两倍。
你的标题谈到FOREIGN KEY
,实际上,重要的是索引。 (如果索引尚不存在,FK将创建索引。)