3

我还能做些什么来优化这个查询?

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

谢谢

4

6 回答 6

9

分析器对此查询说了什么?如果不知道表中有多少行,您就无法判断任何优化。所以运行分析仪,你会看到哪些零件的成本是多少。

于 2009-02-12T10:34:29.827 回答
5

当然,正如@theomega 所说,看执行计划。

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

因此,以下是对您的陈述的一些观察,可能会使事情变慢:

  • 几个外连接(使优化器很难找出要使用的索引)
  • 一组由
  • 很多列分组

据我了解您的 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)

在哪里

当然,这会丢失您外部加入的表中的信息,我建议尝试通过子选择添加所需的列:

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

这样,您可以摆脱一个外部联接和分组依据。外连接被子选择替换,因此需要权衡取舍,这可能对“更干净”的语句不利。

根据 item 和 myItems 之间的基数,您可以执行相同的操作,或者您必须坚持使用外部连接(但无需重新引入 group by)。

希望这可以帮助。

于 2009-02-12T11:35:16.157 回答
1

一些快速的半随机想法:

您的 itemID 和 userID 列是否已编入索引?

如果在查询的开头添加“EXPLAIN”并运行它会发生什么?它使用索引吗?他们明智吗?

您是否需要运行整个内部查询并对其进行过滤,或者您可以将where myTable.userIDFav = 3 or myTable.userIDFav is null部分移动到内部查询中吗?

于 2009-02-12T10:36:30.993 回答
0

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

于 2009-02-12T10:40:21.793 回答
0

您不能将 where 子句myTable.userIDFav = 3 或 myTable.userIDFav is null添加到WHERE ( item.deleted = 0)吗?

问候
利文

于 2009-02-12T10:50:10.350 回答
0

Look at the way your query is built. You join a lot of stuff, then limit the output to 20 rows. You should have the outer join on items and myitems, since your conditions only apply to these two tables, limit the output to the first 20 rows, then join and aggregate. Here you are performing a lot of work that is going to be discarded.

于 2009-02-12T21:31:01.293 回答