【发布时间】:2020-10-24 12:16:23
【问题描述】:
我有 3 张桌子:
产品(1 500 000 行)
+------------+-------------+-------------+-------------+
| id | shop | brand | category |
+------------+-------------+-------------+-------------+
id int(11), AI, PK;
shop int(11);
brand int(11);
category int(11);
标签(1 300 000 行)
+------------+------------+-------------+
| id | product | tag |
+------------+------------+-------------+
id int(11), AI, PK;
product int(11) - it's id from 'products' table;
tag int(11);
大小(1 300 000 行)
+------------+------------+-------------+
| id | product | size |
+------------+------------+-------------+
id int(11), AI, PK;
product int(11) - it's id from 'products' table;
tag int(11);
每一列都有索引。
我需要过滤可能按品牌、商店、类别、标签、尺寸过滤的所有产品(包括计数行)。因此,例如,如果我只需要显示品牌 = 1 和商店 = 1 的产品,我将不会使用 tags 和 sizes 表。这很简单。但问题是,当我想展示属于某些类别、某些商店、具有某些品牌、某些标签和某些尺寸的所有产品时。
有很多组合可以缓存所有这些并更新。获取实时计数的成本约为 6 秒。由于分页的限制,显示所有过滤的产品很快。
我已经花了一周多的时间来测试什么更快,哪个数据库的选项和结构更好,但绝对不知道让它比这更快:
select p.id
FROM
products p
INNER JOIN tags t ON(p.id = t.product and tags=2)
INNER JOIN sizes s ON(p.id = s.product and sizes in (1,2))
WHERE
p.shop in (1,13,31,65)
and
p.category in (270,126,127,144,143,145,146,839,147,148,149,150,158,151,155,157,123,124,128,129,602,120,121,122,152,153,154,482,526,40,42,46,115,119,138,142,133,135,136,137,130,131,132,116,117,32,103,485,112,113,114,566,39,107,108,109,110,118,265,516,527,528,529,530,106,159,161,185,30,86,87,88,89,90,91,92,267,531,532,104,105,28,29,31,33,34,35,36,37,38,41,43,44,45,102,165,269,487,2)
GROUP BY p.id
现在只有 1,500 万个产品,基于具有 20 万个产品的类别的过滤(由于树顶)正在加载(计数和显示数据)大约 5 秒。这是因为过滤的产品在 200k 产品类别中有 13k 行的结果。但仍然需要在所有数据表中进行比较和搜索。解决方案之一可能是将所有产品分离到 f.e. 10 个表格类别(用于服装、电子产品、药店、食品......)并在那里进行搜索。但我不认为这是解决问题的最佳方法。只是比现在更好。
使用order by p.id DESC limit 0,120 执行此 SQL 的结果非常快。大约 0,8 秒,但在某些情况下计算它们大约是 8-12 秒。是否有机会通过更改 SQL 查询或更改 DB 结构来获得更快的结果和计数?
感谢您的帮助。
【问题讨论】:
-
“每列都有索引”不一定是使用索引的最佳解决方案。覆盖索引可能会提高速度(请参阅:stackoverflow.com/questions/8213235/…)
-
您需要一次获取所有数据吗?限制获取的行可能也有帮助
-
试验索引和 Luuk 建议的覆盖索引的好方法是使用 EXPLAIN。
-
@Luuk 我会尽力让你知道的。
-
@MetaPakistani 正如我所说,我不需要每页仅使用 120 个数据。但是,如果我想知道显示了多少页并使用类别标题中的数字,我需要计算所有这些。
标签: php mysql performance filter database-performance