我有一个名为项目的innodb表,可以为一个电子商务网站提供支持。搜索系统允许您搜索可选/附加字段,以便您可以例如仅搜索已修复的计算机或仅超过2000的汽车。
这是通过名为 items_fields 的附加表格完成的。 它的设计非常简单:
+------------+------------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| field_id | int(11) | NO | MUL | NULL | |
| item_id | int(11) | NO | MUL | NULL | |
| valueText | varchar(500) | YES | | NULL | |
| valueInt | decimal(10,1) unsigned | YES | | NULL | |
+------------+------------------------+------+-----+---------+----------------+
还有一个名为 fields 的表格,其中仅包含字段名称和类型。
返回搜索结果的主查询如下:
SELECT items...
FROM items
WHERE items... AND (
SELECT count(id)
FROM items_fields
WHERE items_fields.field_id = "59" AND items_fields.item_id = items.id AND
items_fields.valueText = "Damaged")>0
ORDER by ordering desc LIMIT 35;
大规模(每天仅400万次搜索查询),我需要进一步优化这些高级搜索。目前,平均高级搜索查询大约需要100毫秒。
如何加快此查询?您有任何其他建议,建议,以进行优化吗?这两个表都是innodb,服务器堆栈绝对棒,但是我仍然有这个查询来解决:)
答案 0 :(得分:0)
为(item_id,field_id,valueText)添加和索引,因为这是您的搜索。
摆脱内心的选择!高达5.5的MySQL无法使用内部选择优化查询。据我所知,MariaDB 5.5是目前唯一支持内部选择优化的MySQL替代品。
SELECT i.*, f2.* as damageCounter FROM items i
JOIN items_fields f ON f.field_id = 59
AND f.item_id = i.id
AND f.valueText = "Damaged"
JOIN item_fields f2 ON f2.item_id = i.id
ORDER by i.ordering desc
LIMIT 35;
第一次加入将限制返回的集合。第二个连接将获取满足第一个连接的项目的所有item_fields。在第一个和最后一个连接之间,您可以添加更多连接条件,这些条件将根据其他点过滤掉结果。例如:
SELECT i.*, f3.* as damageCounter FROM items i
JOIN items_fields f ON f.field_id = 59
AND f.item_id = i.id
AND f.valueText = "Damaged"
JOIN items_fields f2 ON f2.field_id = 22
AND f2.item_id = i.id
AND f.valueText = "Green"
JOIN item_fields f3 ON f3.item_id = i.id
ORDER by i.ordering desc
LIMIT 35;
这将返回所有项目的结果集,其中字段59的值为“Damaged”,字段22的值为“Green”及其所有item_fields。