1

我有一个查询,我在 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);
4

2 回答 2

3

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

你是对的,复合索引可能会有所帮助。你甚至可以使它成为一个覆盖索引。我可能会尝试使用索引Grid_Points(Map_Id,X,Y)或索引。Grid_Points(Points,Update_Stamp,User_No)

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

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

以下是我编写该查询的方式,依赖于 and 而不是这么多嵌套括号之间的优先AND顺序OR

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 中,这种方案可能没有这样的优势。

于 2009-12-22T20:01:53.143 回答
1

我不会将其与自身匹配,我会将其作为“分组依据”进行,然后可能会匹配回来以获取此人的身份。

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

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

于 2009-12-22T19:55:40.040 回答