改进这个MySQL查询?

时间:2013-09-25 11:03:04

标签: mysql database database-design

我有一个需要很长时间的查询,我想知道是否有更好的方法吗?也许加入?

它目前耗时约2.5秒,这太长了。

稍微解释一下结构:我有产品,“主题”和“类别”。可以为产品分配任意数量的主题或类别。主题和categoryitems表链接表以将类别/主题ID链接到产品ID。

我想获得至少包含一个主题和类别的所有产品的列表。我目前得到的查询如下:

SELECT *
FROM themes t, themeitems ti, products p, catitems ci, categories c
WHERE t.ID = ti.THEMEID 
AND ti.PRODID = p.ID 
AND p.ID = ci.PRODID 
AND ci.CATID = c.ID 

我实际上只是在执行查询时选择了我需要的行,但我已将其删除以抽象一点。

任何正确方向的帮助都会很棒!

编辑:下面的EXPLAIN

EXPLAIN

5 个答案:

答案 0 :(得分:1)

利用正确的JOIN并确保JOIN中使用的字段上的索引是此问题的标准响应。

SELECT *
FROM themes t
INNER JOIN themeitems ti ON t.ID = ti.THEMEID
INNER JOIN products p ON ti.PRODID = p.ID
INNER JOIN catitems ci ON p.ID = ci.PRODID
INNER JOIN categories c ON ci.CATID = c.ID 

JOIN的规范帮助查询引擎计算出它需要做什么,并且连接中使用的列上的索引将实现更快速的连接。

答案 1 :(得分:1)

您的查询速度很慢,因为您的表上没有任何索引。

尝试:

create unique index pk on themes (ID)
create index fk on themeitems(themeid, prodid)
create unique index pk on products (id)
create index fk catitems(prodid, catid)
create unique index pk on categories (id)

正如@symcbean在评论中所写,catitems和主题索引也应该是唯一索引 - 如果没有其他列要添加到该索引(例如“validityDate”),请将其添加到create语句中。

答案 2 :(得分:0)

您的查询非常简单。我不认为通过实现连接会降低您的成本。您可以尝试将索引放到适当的列

答案 3 :(得分:0)

简单地选择较少的数据是明显的解决方案。

为什么每次运行查询时都需要知道每一列和每一行?解决这三个因素中的任何一个都将提高绩效。

  

我想获得至少包含一个主题和类别的所有产品的列表

这意味着你不关心哪个主题和类别,在这种情况下......

SELECT p.*
FROM themeitems ti, products p, catitems ci
WHERE p.ID = ti.PRODID  
AND p.ID = ci.PRODID  

有可能使查询运行得更快 - 但是您没有提供表结构,索引,数据量,引擎类型,查询缓存配置,数据更新频率,查询运行的频率.....

<强>更新

既然您已经提供了解释计划,那么显然您的数据量非常少且没有相关指数!!!!!

至少应该在themeitems和catitems表中的产品外键上添加索引。实际上,这些表的主键应该是产品ID和类别ID /主题ID,并且由于您可能拥有的产品多于类别或主题,因此字段应该在索引中按此顺序排列。 (即PRODID,CATID而不是CATID,PRODID)

<强> UPDATE2

鉴于要求“获取至少具有一个主题和类别的所有产品的列表”,它可能会更快(但最大的胜利是减少连接数并添加正确的索引)到....

SELECT p.*
FROM product p
INNER JOIN (
    SELECT DISTINCT ti.PRODID
    FROM themeitems ti, catitems ci
    WHERE ti.PRODID=ci.PRODID
) i ON p.id=i.PRODID

答案 4 :(得分:0)

我已做出回答,因为我无法将其作为评论

如果要使用JOINS删除FULL表扫描,请执行基本滑动操作。 你应该先索引。

注意,这并不总是与ORDER BY / GROUP BY结合使用JOIN,因为经常使用临时;需要使用filesort。

额外,因为这不在问题的范围之外,以及如何使用ORDER BY / GROUP BY结合JOIN修复慢查询

因为MySQL优化器认为它需要首先访问最小的表以获得最佳执行,这将导致MySQL无法始终使用索引对结果进行排序,并且需要使用临时表和filesort修复错误的排序顺序< / p>

(在这里阅读更多相关信息MySQL slow query using filesort这就是我如何解决这个问题,因为当MySQL需要基于磁盘的临时表时,使用临时确实可以扼杀性能)