2013-11-14 83 views
1

我有一个mysql sql选择,这种方式需要很长时间才能返回数据。提高mysql查询的性能

╔════════════════╗ ╔════════════════╗ 
║ 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; 

EXPLAIN SQL EXPLAIN

。该查询我的努力,以减少和改善的结果。我已经从最初花费180秒的查询变成了现在花费了大约20秒但仍然不够的原始查询。

任何人都可以提供此查询的性能改进?

我们正在搜索数百万行的数据,所以每一点点都会有所帮助。

+0

如果你注释掉select语句中的三个子查询,它运行得有多快? –

+3

在此处发布解释说明的输出。 – Namphibian

+0

另外,item_category_xref中是否有精选字段? –

回答

0

您的子查询中使用的许多字段不是索引的一部分。如果您打算在这些查询中使用它,请尝试创建与这些子查询相对应的复合索引。你可能不需要全部(这取决于你的表有多大以及数据如何分布)。

此外,你没有指定你的tracking_action表的外观,但我看到你在那里使用的是文本字段(如果它是一个文本字段),如果那个没有索引,那么它也会减慢查询速度。

我会尝试创造(一些)以下综合指数:

item_category_xref - (item_id, featured) and (item_id, category_id) 
tracking_action - (context_guid, context, action) 
item_image - (item_id, sequence) 
0

我想将你的子查询中的全部查询到更合适的地方。任何你想要的结果,加入他们的子查询到项目表。你想比较的东西应该放在where字段中。此外,您在查询中比较的任何内容都需要编入索引。明显的是delete字段,但我会包含跟踪操作context_guidaction字段,可能是一个组合索引。此外,我会确保在您的查询中正确引用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); 
+0

复制和粘贴正是你所拥有的,它踢回一个错误。 未知列'ta1。行动'在'有条款' – kasdega

+0

你的tracking_action表中的列是什么?在原始查询中引用行动列 –

+0

如果ta1.action未抛出错误,请继续并删除明确的引号并重试。 –