[英]Improve performance of mysql query
我有一个mysql sql select,它花了很长时间返回数据。
表
╔════════════════╗ ╔════════════════╗
║ ITEM ║ ║ Workspace ║
╠════════════════║ ╠════════════════║
║ id ║ ║ id ║
║ guid ║ ║ guid ║
║ workspace_id ║ ║ company_id ║
║ deleted ║ ║ deleted ║
╚════════════════╝ ╚════════════════╝
Indexes: id, guid Indexes: id, guid,
workspace_id company_id
╔════════════════╗ ╔════════════════════╗
║ COMPANY ║ ║ item_category_xref ║
╠════════════════║ ╠════════════════════║
║ id ║ ║ item_id ║
║ deleted ║ ║ category_id ║
╚════════════════╝ ╚════════════════════╝
Indexes: id Indexes: item_id, category_id
╔════════════════╗ ╔═════════════════════╗
║ item_image ║ ║ tracking_action ║
╠════════════════║ ╠═════════════════════║
║ item_id ║ ║ id ║
║ sequence ║ ║ guid ║
╚════════════════╝ ║ action ║
Indexes: ║ context ║
(item_id, sequence) ║ deleted ║
╚═════════════════════╝
SQL
SELECT
itm.id "item.id",
ws.id "workspace.id",
co.id "company.id",
((SELECT count(*) FROM item_category_xref icx
WHERE icx.item_id = itm.id
AND icx.featured = 1) > 0) "featured",
(SELECT COUNT(*) FROM tracking_action ta1
WHERE ta1.context = 'ITEM'
AND ta1.context_guid = itm.guid
AND ta1.action = 'VIEW') ta_view_count ,
(SELECT COUNT(*) FROM tracking_action ta2
WHERE ta2.context = 'ITEM'
AND ta2.context_guid = itm.guid
AND ta2.action = 'SEARCH_RESULT') ta_search_count
FROM item itm
JOIN workspace ws
ON itm.workspace_id = ws.id
AND ws.deleted != 1
JOIN company co
ON ws.company_id = co.id
AND co.deleted != 1
JOIN item_category_xref icx
ON itm.id = icx.item_id
AND icx.category_id = 1
LEFT JOIN item_image ii
ON itm.id = ii.item_id
AND ii.sequence = 1
WHERE itm.deleted != 1
HAVING featured > 0;
说明
该查询是我努力减少和改进的结果。 我已经从最初的查询花费了180秒减少到现在的大约20秒,但仍然不够。
谁能为此查询提供性能改进?
我们正在搜索几百万行数据,因此每一点都会有所帮助。
子查询中使用的许多字段都不属于索引。 如果打算在此类查询中大量使用它,请尝试创建与这些子查询相对应的复合索引。 您可能不需要全部(这取决于表的大小以及其中的数据分布方式)。
另外,您没有指定trace_action表的外观,但是我看到您在此处使用文本字段(如果它是文本字段),如果该字段未建立索引,那么它也会减慢查询速度。
我将尝试创建以下一些复合索引:
item_category_xref - (item_id, featured) and (item_id, category_id)
tracking_action - (context_guid, context, action)
item_image - (item_id, sequence)
我会将您的子查询移至整体查询中的更适当位置。 您想要的结果中的任何内容,都可以将其子查询加入到item表中。 要比较的对象应该在where字段中。 此外,您在查询中比较的所有内容都需要建立索引。 显而易见的一个是delete
字段,但是我将包括跟踪动作context_guid
和action
字段,可能作为复合索引。 我还要确保在查询中正确引用action
,因为它是保留字。
这将给您带来额外的好处,即能够分解每个子查询并单独测试它们以查找性能问题。 这将使您能够隔离有问题的表或索引。
这是我的粗略观点,语法可能并不完美。
SELECT
itm.id "item.id",
ws.id "workspace.id",
co.id "company.id",
tav.ta_view_count,
tas.ta_search_count
FROM item itm
LEFT JOIN (SELECT ta1.context_guid, COUNT(*) as ta_view_count FROM tracking_action ta1 GROUP BY ta1.context_guid HAVING ta1.context_guid = 'ITEM' AND ta1.`action` = 'VIEW') tav ON tav.context_guid = itm.guid
LEFT JOIN (SELECT ta2.context_guid, COUNT(*) as ta_search_count FROM tracking_action ta2 GROUP BY ta2.context_guid HAVING ta2.context_guid = 'ITEM' AND ta2.`action` = 'SEARCH_RESULT') tas ON tas.context_guid = itm.guid
WHERE itm.deleted != 1 AND
itm.id IN (SELECT icx.item_id, COUNT(*) featured FROM item_category_xref icx GROUP BY icx.item_id HAVING featured > 0) AND
itm.id IN (SELECT company.id FROM company WHERE company.deleted != 1) AND
itm.id IN (SELECT workspace.id FROM workspace WHERE workspace.deleted != 1) AND
itm.id IN (SELECT item_image.id FROM item_image WHERE item_image.sequence != 1);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.