我正在使用看起来像这样的遗留数据库模式:
product_table
表包含字段:
uid
(int,主键)
name
(varchar 50)
category
表包含字段:
uid
(int,主键)
name
(varchar 50)
好吧,现在product_table
与类别表有4个MM关系:
product_table__category_1__mm
有字段:
uid_local
(int,包含product_table.uid
)
uid_foreign
(int,包含category.uid
)
product_table__category_2__mm
有字段:
uid_local
(int,包含product_table.uid
)
uid_foreign
(int,包含category.uid
)
product_table__category_3__mm
有字段:
uid_local
(int,包含product_table.uid
)
uid_foreign
(int,包含category.uid
)
product_table__category_4__mm
有字段:
uid_local
(int,包含product_table.uid
)
uid_foreign
(int,包含category.uid
)
(是的,所有4个MM表都有相同的字段,都与category
表相关)
所以,如果我想根据用户选择的int值拉入所有四个连接和过滤器,它将看起来像这样:
select
product_table.*
from
product_table
inner join product_table__category_1__mm mm_1 on mm_1.uid_local = product_table.uid
inner join category cat_1 on cat_1.uid = mm_1.uid_foreign and cat_1.uid in (7, 8)
inner join product_table__category_2__mm mm_2 on mm_2.uid_local = product_table.uid
inner join category cat_2 on cat_2.uid = mm_2.uid_foreign and cat_2.uid in (63, 52)
inner join product_table__category_3__mm mm_3 on mm_3.uid_local = product_table.uid
inner join category cat_3 on cat_3.uid = mm_3.uid_foreign and cat_3.uid in (84, 12)
inner join product_table__category_4__mm mm_4 on mm_4.uid_local = product_table.uid
inner join category cat_4 on cat_4.uid = mm_4.uid_foreign and cat_4.uid in (16, 33)
group by product_table.uid ### --> in order to get unique results
现在这是一个大问题,但我无法改变数据库设计,因为它已经被广泛使用。
有关如何更快地进行此查询的任何想法?你会把索引放在哪里?
答案 0 :(得分:0)
在任何特定时刻,您不太可能同时需要所有这些数据。如果我错了,你可以纠正我,但如果这在任何地方被用作“主”查询,我会:
将其分解为仅使用特定操作中所需表格的较小查询,
使用Select field1,field2 .etc而不是Select *,仅指定特定操作所需的字段,
确保所有主键和外键都有索引。
答案 1 :(得分:0)
嗯,“mm”表中的两个字段都应该被编入索引,产品表上的uid字段和类别表上的uid也应该被编入索引。但我的猜测是所有这些字段都已编入索引。
为了更容易理解针对该混乱的查询,您可能还需要考虑将上面发布的查询也放到视图中。
答案 2 :(得分:0)
你需要在这里摆脱GROUP BY
。
MySQL
不善于优化它。
重写您的查询:
SELECT *
FROM product_table
WHERE EXISTS
(
SELECT NULL
FROM product_table__category_1__mm mm_1
JOIN category cat_1
ON cat_1.uid = mm_1.uid_foreign
WHERE mm_1.uid_local = product_table.uid
AND mm_1.uid_foreign IN (7, 8)
)
AND
…
创建索引:
product_table__category_*__mm (uid_local, uid_foreign)
或者更好的是,在PRIMARY KEYs
上声明product_table__category_*__mm
:
ALTER TABLE product_table__category_*__mm ADD CONSTRAINT pk_pc*mm_local_foreign (uid_local, uid_foreign)