以下查询用于在电子商务网站上搜索产品数据库时应用多个过滤值。
When you use more than 7 filters, MySQL server goes down.
- 有机会加入
positions_categories_links
一次吗? - 我应该考虑更改数据库结构吗?
Each product has one
eshop_cats
category (many2one) and up to 20categories
with multiple relations (many2many).
表 eshop_pos
有 40,000 条记录并包含产品。
表 eshop_cats
有 340 条记录并包含主要类别。
表 categories
有 6000 条记录并包含 Duplex Categories。
表 positions_categories_links
有 360,000 条记录,包含 Products 和 Categories 之间的键。
这是我的查询:
SELECT COUNT(DISTINCT eshop_pos.id)
FROM eshop_pos
INNER JOIN eshop_cats t1 ON eshop_pos.eshopcatid = t1.id
AND t1.active = 1
INNER JOIN positions_categories_links t2 ON t2.pos_id = eshop_pos.id
INNER JOIN categories t3 ON t3.id = t2.cat_id
AND t3.active = 1
AND t3.section_id = 62021
INNER JOIN positions_categories_links t4 ON t4.pos_id = eshop_pos.id
INNER JOIN categories t5 ON t5.id = t4.cat_id
AND t5.active = 1
AND t5.section_id = 62023
INNER JOIN positions_categories_links AS duplex_links_51 ON duplex_links_51.pos_id = eshop_pos.id
AND duplex_links_51.cat_id = 51
AND duplex_links_51.value IN (2984)
INNER JOIN positions_categories_links AS duplex_links_52 ON duplex_links_52.pos_id = eshop_pos.id
AND duplex_links_52.cat_id = 52
AND duplex_links_52.value IN (3003)
INNER JOIN positions_categories_links AS duplex_links_3904 ON duplex_links_3904.pos_id = eshop_pos.id
AND duplex_links_3904.cat_id = 3904
AND duplex_links_3904.value IN (3941)
INNER JOIN positions_categories_links AS duplex_links_4462 ON duplex_links_4462.pos_id = eshop_pos.id
AND duplex_links_4462.cat_id = 4462
AND duplex_links_4462.value IN (4465)
INNER JOIN positions_categories_links AS duplex_links_4466 ON duplex_links_4466.pos_id = eshop_pos.id
AND duplex_links_4466.cat_id = 4466
AND duplex_links_4466.value IN (4468)
INNER JOIN positions_categories_links AS duplex_links_4472 ON duplex_links_4472.pos_id = eshop_pos.id
AND duplex_links_4472.cat_id = 4472
AND duplex_links_4472.value IN (4473)
INNER JOIN positions_categories_links AS duplex_links_4974 ON duplex_links_4974.pos_id = eshop_pos.id
AND duplex_links_4974.cat_id = 4974
AND duplex_links_4974.value IN (4978)
INNER JOIN positions_categories_links AS duplex_links_4979 ON duplex_links_4979.pos_id = eshop_pos.id
AND duplex_links_4979.cat_id = 4979
AND duplex_links_4979.value IN (4982)
INNER JOIN positions_categories_links AS duplex_links_4984 ON duplex_links_4984.pos_id = eshop_pos.id
AND duplex_links_4984.cat_id = 4984
AND duplex_links_4984.value IN (4986)
我无法在服务器上运行查询的 EXPLAIN。但是,它在我的本地笔记本电脑上运行良好:
最佳答案
您的查询格式略有改变。我还将别名引用从您的“duplex_links”引用更改为缩写别名“PCL”(来自您的 Position_categories_links 表)。更短且相关的帮助表引用(至少对我和其他人而言)。
至于您的表/索引,如果它们尚不存在,我建议使用以下表/索引。在这种情况下,我为您的查询提供了所有覆盖索引,这意味着由于用于满足所有连接条件的列是索引的一部分,sql 数据库不必转到底层实际数据页来确认其他详细信息,因此帮助提高性能。
Table Index
eshop_pos (id, eshopcatid)
eshop_cats (id, active)
positions_categories_links (pos_id, cat_id, value)
categories (id, active, section_id)
我还喜欢显示连接位置之间的缩进相关性,这样您就知道如何从一个表/别名进入下一个级别。您可以直接看到事物的来源层次结构。
SELECT
COUNT(DISTINCT eshop_pos.id)
FROM
eshop_pos
inner join eshop_cats t1
on eshop_pos.eshopcatid = t1.id
AND t1.active = 1
inner join positions_categories_links t2
on eshop_pos.id = t2.pos_id
inner join categories t3
on t2.cat_id = t3.id
and t3.active = 1
and t3.section_id = 62021
inner join positions_categories_links t4
on eshop_pos.id = t4.pos_id
inner join categories t5
on t4.cat_id = t5.id
and t5.active = 1
and t5.section_id = 62023
INNER JOIN positions_categories_links AS PCL51
ON eshop_pos.id = PCL51.pos_id
AND PCL51.cat_id = 51
and PCL51.value in (2984)
INNER JOIN positions_categories_links AS PCL52
ON eshop_pos.id = PCL52.pos_id
AND PCL52.cat_id = 52
and PCL52.value in (3003)
INNER JOIN positions_categories_links AS PCL3904
ON eshop_pos.id = PCL3904.pos_id
AND PCL3904.cat_id = 3904
and PCL3904.value in (3941)
INNER JOIN positions_categories_links AS PCL4462
ON eshop_pos.id = PCL4462.pos_id
AND PCL4462.cat_id = 4462
and PCL4462.value in (4465)
INNER JOIN positions_categories_links AS PCL4466
ON eshop_pos.id = PCL4466.pos_id
AND PCL4466.cat_id = 4466
and PCL4466.value in (4468)
现在,拥有适当的索引来帮助优化查询是一回事,但不断地对这样的多个条件进行计数可能有点矫枉过正。如果您有一个已知的特定详细级别,例如您在此处所做的特定类别,那肯定会有所帮助。
(删除了不保证所有标准的“或”版本)
关于php - 在同一个表上的多个连接似乎影响性能的情况下,如何改进此查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48717396/