select COUNT(p.id) AS `num`, cat.id, cat.name, cat.parent_id AS `parent_id`
from products p
INNER JOIN `products_categories` AS `pc` ON p.id=pc.products_id
INNER JOIN `categories` AS `cat` ON pc.categories_id=cat.id
WHERE p.status = 1 AND p.gender IN ('female','neutral')
group by cat.id
解释查询:
1 SIMPLE p ref PRIMARY,gender,status status 1 const 139107 Using where; Using temporary; Using filesort
1 SIMPLE pc ref products_id,categories products_id 4 mydb.p.id 1 Using index
1 SIMPLE cat eq_ref PRIMARY,categoryname PRIMARY 4 mydb.pc.categories_id 1 Using where
相关指数:
products 0 PRIMARY 1 id A 299339 BTREE
products 1 title 1 title A 299339 BTREE
products 1 sku 1 sku A 299339 BTREE
products 1 body 1 body A 299339 200 BTREE
products 1 short_description 1 short_description A 299339 200 YES BTREE
products 1 keywords 1 keywords A 2 200 BTREE
products 1 gender 1 gender A 10 BTREE
products 1 status 1 status A 2 BTREE
products 1 brand_id 1 brand_id A 3741 YES BTREE
products 1 merchant 1 merchant_id A 52 BTREE
products 1 title_2 1 title,body,keywords 299339 FULLTEXT
products 1 title_3 1 title 299339 FULLTEXT
products 1 body_2 1 body 299339 FULLTEXT
products_categories 0 PRIMARY 1 id A 514054 BTREE
products_categories 1 products_id 1 products_id, categories_id A 514054 BTREE
products_categories 1 categories 1 categories_id A 266 BTREE
categories 0 PRIMARY 1 id A 154 BTREE
categories 1 categoryname 1 name A 154 BTREE
这是一个包含产品,类别和它们之间的N:N关系的数据库。产品可以是1个或更多类别。
我基本上需要一个查询告诉我,对于我当前的产品过滤器(在这种情况下是状态和性别),如果该类别有任何产品(所以我可以隐藏没有产品的类别)。目前我统计每个类别中的产品都知道这一点。
查询WHERE参数将根据用户选择的过滤器进行更改,以便该部分在此优化中不是非常重要。
我不需要确切的产品数量,只要他们有产品。产品表有不少索引,有products_categories和categories表。产品表有大约400k产品,150个类别和500k产品_categories。
在AWS RDS上托管的MySQL 5.6.22,InnoDB中的所有表。
我理解我的解释查询显示为什么这很慢(通过很多产品),但我没有任何想法如何优化这个...可能有不同的方式来考虑这个?
答案 0 :(得分:0)
对于此查询:
#table-of-grades
您需要所有select COUNT(p.id) AS `num`, cat.id, cat.name, cat.parent_id AS `parent_id`
from products p INNER JOIN
products_categories `pc`
ON p.id = pc.products_id INNER JOIN
categories cat
ON pc.categories_id = cat.id
WHERE p.status = 1 AND p.gender IN ('female', 'neutral')
group by cat.id;
键的索引。我建议join
,products(status, gender, id)
和products_categories(products_id, categories_id)
。
有时,在MySQL中,使用相关子查询比使用categories(id)
更快:
group by
此版本需要select c.*,
(select count(*)
from products_categories `pc` INNER JOIN
products p
ON p.id = pc.products_id
where pc.categories_id = cat.id AND
p.status = 1 AND p.gender IN ('female', 'neutral')
) as cnt
from categories c;
和products_categories(categories_id, products_id)
上的索引。
答案 1 :(得分:0)
您的查询返回139107个匹配记录,因为您使用的过滤条件不是很有限(状态= 1,性别=女性或中性)。试试这个
this.request.post(
requestData,
function (successResponse) {
// Do whatever with response
},
function (failResponse) {
// Do whatever with response
}
);
添加url
不会自动改善查询。问题是您的过滤条件会返回许多匹配的产品。按性别或布尔状态(true / false)过滤记录可能会因为许多重复值而导致表扫描,即使状态和性别是索引,MySQL仍然认为运行表扫描比使用索引更便宜。
requestData
用于过滤没有产品的任何类别。试试这个
SELECT cat.id, cat.name, cat.parent_id AS `parent_id`,
COUNT(p.id) AS `num`
FROM `categories` AS `cat`
INNER JOIN `products_categories` AS `pc` ON pc.categories_id=cat.id
INNER JOIN products AS p ON p.id=pc.products_id
WHERE p.status = 1 AND p.gender IN ('female','neutral')
GROUP BY cat.id
HAVING COUNT(p.id)>0
以上查询不会与产品表一起加入。如果他们有产品关联,只需查看product_categories。