0

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

目前大约需要 2.5 秒,这太长了。

稍微解释一下结构:我有产品、“主题”和“类别”。可以为产品分配任意数量的主题或类别。themeitems 和 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 

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

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

编辑:在下面解释

解释

4

5 回答 5

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 的规范有助于查询引擎确定它需要做什么,并且连接中使用的列上的索引将实现更快速的连接。

于 2013-09-25T11:07:04.323 回答
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 和 themeitems 索引也应该是唯一索引 - 如果没有其他列要添加到该索引(例如“validityDate”),请将其添加到 create 语句中。

于 2013-09-25T11:17:02.993 回答
0

您的查询非常简单。我认为您的成本不会随着实施联接而降低。您可以尝试将索引放入适当的列

于 2013-09-25T11:07:40.660 回答
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)

更新2

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

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
于 2013-09-25T11:11:45.577 回答
0

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

如果您想使用 JOINS 删除完整的表扫描,则基本的拇指关闭操作。你应该先索引。

请注意,这并不总是与 ORDER BY/GROUP BY 与 JOINS 结合使用,因为通常是 Using 临时的;需要使用文件排序。

额外因为这超出了问题的范围以及如何使用 ORDER BY/GROUP BY 结合 JOIN 来修复慢查询

因为 MySQL 优化器认为它需要首先访问最小的表以获得最佳执行,这将导致 MySQL 不能总是使用索引对结果进行排序,需要使用临时表和文件排序来修复错误的排序顺序

(在这里阅读更多关于使用文件排序的 MySQL 慢查询这是我解决此问题的方法,因为当 MySQL 需要基于磁盘的临时表时,使用临时确实会降低性能)

于 2013-09-28T16:46:23.510 回答