优化SQL查询

RSi*_*lva 3 mysql sql optimization inner-join left-join

我还可以做些什么来优化此查询?

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 
Run Code Online (Sandbox Code Playgroud)

我正在使用MySQL

谢谢

the*_*ega 9

分析器对此查询说了什么?如果没有关于表格中有多少行的知识,您就无法进行任何优化.因此,运行分析仪,您将看到哪些部件成本.


Tho*_*ten 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)
Run Code Online (Sandbox Code Playgroud)

哪里

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

SELECT `item`.itemID, 
       (SELECT count (itemID)
        FROM votes v
       WHERE v.itemID = 'item'.itemID) as 'votes', <etc.>
Run Code Online (Sandbox Code Playgroud)

这样,您可以删除一个外连接和组.外连接由子选择替换,因此存在权衡,这可能对"清洁"语句不利.

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

希望这可以帮助.