2009-02-12 156 views
3

我还能做些什么来优化此查询?优化SQL查询

SELECT * FROM 
    (SELECT `item`.itemID, COUNT(`votes`.itemID) AS `votes`, 
      `item`.title, `item`.itemTypeID, `item`. 
      submitDate, `item`.deleted, `item`.ItemCat, 
      `item`.counter, `item`.userID, `users`.name, 
      TIMESTAMPDIFF(minute,`submitDate`,NOW()) AS 'timeMin' , 
      `myItems`.userID as userIDFav, `myItems`.deleted as myDeleted 
     FROM (votes `votes` RIGHT OUTER JOIN item `item` 
        ON (`votes`.itemID = `item`.itemID)) 
      INNER JOIN 
       users `users` 
      ON (`users`.userID = `item`.userID) 
    LEFT OUTER JOIN 
       myItems `myItems` 
      ON (`myItems`.itemID = `item`.itemID) 
    WHERE (`item`.deleted = 0) 
    GROUP BY `item`.itemID, 
       `votes`.itemID, 
       `item`.title, 
       `item`.itemTypeID, 
       `item`.submitDate, 
       `item`.deleted, 
       `item`.ItemCat, 
       `item`.counter, 
       `item`.userID, 
       `users`.name, 
       `myItems`.deleted, 
       `myItems`.userID 
    ORDER BY `item`.itemID DESC) as myTable 
where myTable.userIDFav = 3 or myTable.userIDFav is null 
      limit 0, 20 

我使用MySQL

感谢

回答

5

当然,作为@theomega说,看执行计划。

但我也建议尝试“清理”你的陈述。 (我不知道哪一个更快 - 这取决于你的表格大小。)通常,我会尝试从一个干净的声明开始,并从那里开始优化。但通常情况下,干净的声明使优化器可以更容易地制定出良好的执行计划。

因此,这里有你的语句可能会使事情慢一些意见:

  • 一对夫妇外的连接(使得它很难为optimzer找出一个索引使用)的
  • 一组
  • 通过

据我理解你的SQL很多组列,这句话应该做的大部分东西你是做:

SELECT `item`.itemID, `item`.title, `item`.itemTypeID, `item`. 
     submitDate, `item`.deleted, `item`.ItemCat, 
     `item`.counter, `item`.userID, `users`.name, 
     TIMESTAMPDIFF(minute,`submitDate`,NOW()) AS 'timeMin' 
    FROM (item `item` INNER JOIN users `users` 
     ON (`users`.userID = `item`.userID) 

WHERE

当然,这丢了你外连接的表的信息,我建议你尝试通过子选择添加所需的列:

SELECT `item`.itemID, 
     (SELECT count (itemID) 
     FROM votes v 
     WHERE v.itemID = 'item'.itemID) as 'votes', <etc.> 

这样,你可以通过删除一个外部联接和组。外部连接被替换后的替代,所以存在一个折衷,这对于“更干净”的语句可能是不利的。

根据item和myItems之间的基数,您可以做同样的事情,或者您必须坚持外连接(但不需要重新引入分组)。

希望这会有所帮助。

9

什么是分析此查询说呢?不知道表中有多少行,你不能告诉任何优化。所以运行分析仪,你会看到哪些部件需要花费什么。

1

一些快速的半随机想法:

您的itemID和userID列索引?

如果将“EXPLAIN”添加到查询的开头并运行它会发生什么?它使用索引吗?他们是否合理?

你需要运行整个内部查询和过滤器,或者你可以把where myTable.userIDFav = 3 or myTable.userIDFav is null部分移动到内部查询中吗?

0

你好似在Group By列表中有太多的字段,因为其中一个是itemID,我怀疑你可以使用内部SELECT来执行分组,并使用外部SELECT来返回所需的字段集合。

0

不能添加where子句myTable.userIDFav = 3或myTable.userIDFav为空WHERE(item .deleted = 0)

问候
利芬

0

看看你的查询的构建方式。你加入了很多东西,然后将输出限制为20行。由于条件仅适用于这两个表,因此您应该对项目和myitems有外连接,将输出限制为前20行,然后进行连接和聚合。在这里,你正在执行许多将被丢弃的工作。