mysql查询调优

时间:2009-12-22 19:40:33

标签: sql mysql greatest-n-per-group

我有一个查询,我已经进入MYSQL视图。这个特殊的视图对我们的应用程序至关重要,所以我们正在考虑调整它。 Map_Id,User_No,X,Y上有一个主键。我很乐于调整SQL服务器查询,但不完全确定MySql在这方面的工作原理。是否有助于在其上放置一个涵盖点和update_stamp的索引?此表上的读数为90%,因此虽然它具有大量插入,但它与读取量无法比较。

描述:获取给定地图中每个x,y坐标分数最多的人。由谁拥有最新的更新标记,然后是用户ID。

    SELECT GP.Map_Id AS Map_Id,GP.User_No AS User_No,GP.X AS X,GP.Y AS Y, GP.Points AS Points,GP.Update_Stamp AS Update_Stamp
    FROM (Grid_Points GP LEFT JOIN Grid_Points GP2
         ON (
       (
        (GP2.Map_Id = GP.Map_Id) AND (GP2.X = GP.X) AND (GP2.Y = GP.Y) AND 
        ((GP2.Points > GP.Points) OR ((GP2.Points = GP.Points) AND (GP2.Update_Stamp > GP.Update_Stamp)) OR 
        ((GP2.Points = GP.Points) AND (GP2.Update_Stamp = GP.Update_Stamp) AND (GP2.User_No < GP.User_No)))
       )
  )
 )

WHERE ISNULL(GP2.User_No);

2 个答案:

答案 0 :(得分:3)

哇,哇,你真的很喜欢用圆括号。 : - )

你是对的,复合索引可能有所帮助。您甚至可以将其作为覆盖索引。可能是Grid_Points(Map_Id,X,Y)上的索引或Grid_Points(Points,Update_Stamp,User_No)上的索引都是我尝试的。

始终使用EXPLAIN测试查询优化,以查看优化程序是否正在使用您的索引。阅读该文档部分,直到您理解EXPLAIN报告中的神秘笔记。

EXPLAIN报告可能会显示它决定使用哪个索引。您应该知道 MySQL在给定查询中仅使用每个表的一个索引

以下是我将如何编写该查询,依赖于ANDOR之间的优先顺序而不是如此多的嵌套括号:

SELECT GP.Map_Id, GP.User_No, GP.X, GP.Y, GP.Points, GP.Update_Stamp
FROM Grid_Points GP LEFT JOIN Grid_Points GP2
  ON GP2.Map_Id = GP.Map_Id AND GP2.X = GP.X AND GP2.Y = GP.Y
    AND (
      GP2.Points > GP.Points
      OR
        GP2.Points = GP.Points
        AND GP2.Update_Stamp > GP.Update_Stamp
      OR
        GP2.Points = GP.Points
        AND GP2.Update_Stamp = GP.Update_Stamp
        AND GP2.User_No < GP.User_No
    )
WHERE GP2.User_No IS NULL;

您正在使用我最喜欢的方法在MySQL中查找最大n组。 MySQL没有很好地优化GROUP BY(它经常会产生一个被序列化到磁盘的临时表),所以你使用的左外连接解决方​​案通常要好得多,至少对于MySQL来说。在其他品牌的RDBMS中,这种解决方案可能没有这样的优势。

答案 1 :(得分:1)

我不会将它与自己匹配,我会将其作为“分组依据”,然后可能匹配回来以获得该人的身份。

SELECT Map_Id,X,Y,max(Points) FROM Grid_Points GROUP BY Map_Id,X,Y;

这将为您提供Map_Id,X和Y的表格,然后是最大点数。 然后,您可以将这些结果连接回Grid_Points,以查找哪些用户=这些点。