小编典典

如何优化MySQL查询(分组和顺序)

sql

大家好,我有一个需要优化的查询。它的工作原理,但它的狗,表现明智。

内容如下:

SELECT  *
FROM    (
        SELECT  *
        FROM    views
        WHERE   user_id = '1'
        ORDER BY
                page DESC
        ) v
GROUP BY
        v.session

我正在跟踪查看不同页面的视图,并且我想知道每个会话的最高页面,以便了解在任何给定条件下他们的点击量(从头到尾查看所有页面)会议。

基本上,我想做的是在GROUP之前对结果进行排序。以上是实现的,成本很高。

谁能用这个方法拍我的脑袋?谢谢你们!

更新:

说明:

"1" "PRIMARY"   "<derived2>"    "ALL"   \N  \N  \N  \N  "3545"  "Using temporary; Using filesort"

"2" "DERIVED"   "views" "index" \N  "page"  "5" \N  "196168"    "Using where"

模式:

ID       int(8) unsigned  (NULL)     NO      PRI     (NULL)   auto_increment  select,insert,update,references         
page     int(8)           (NULL)     YES     MUL     (NULL)                   select,insert,update,references         
user_id  int(8)           (NULL)     YES             (NULL)                   select,insert,update,references         
session  int(8)           (NULL)     YES             (NULL)                   select,insert,update,references         
created  datetime         (NULL)     NO                                       select,insert,update,references

索引信息:

views            0  PRIMARY              1  ID           A               196008    (NULL)  (NULL)          BTREE

views            1  page                 1  page         A                  259    (NULL)  (NULL)  YES     BTREE

阅读 185

收藏
2021-05-05

共1个答案

小编典典

我正在跟踪查看不同页面的视图,并且我想知道每个会话的最高页面,以便了解在任何给定条件下他们的点击量(从头到尾查看所有页面)会议。

分组之前先订购是一种非常不可靠的方法。

MySQL扩展GROUP BY语法:您可以在SELECTandORDER BY子句中使用未分组和未聚合的字段。

在这种情况下,page每个输出一个随机值session

文档
明确指出,您永远不应对将确切确定为哪个值做任何假设:

如果您从GROUP BY零件中省略的列在组中不是恒定的,请不要使用此功能。服务器可以自由地从组中返回任何值,因此除非所有值都相同,否则结果是不确定的。

但是,实际上,将返回扫描的第一行中的值。

由于您ORDER BY page DESC在子查询中使用,因此该行恰好是page每个会话最多的行。

您不应该依赖它,因为此行为没有记录,并且如果在下一版本中将返回其他行,则不会将其视为错误。

但是,您甚至不必做这些令人讨厌的把戏。

只需使用聚合函数:

SELECT  MAX(page)
FROM    views
WHERE   user_id = '1'
GROUP BY
        session

这是记录在案的,干净的方法来做您想要的。

创建一个复合索引(user_id, session, page)以使查询运行更快。

如果您需要表中的所有列,而不仅是聚合的列,请使用以下语法:

SELECT  v.*
FROM    (
        SELECT  DISTINCT user_id, session
        FROM    views
        ) vo
JOIN    views v
ON      v.id =
        (
        SELECT  id
        FROM    views vi
        WHERE   vi.user_id = vo.user_id
                AND vi.session = vo.session
        ORDER BY
                page DESC
        LIMIT 1
        )

这假设idPRIMARY KEYon views

2021-05-05