mysql 查询缓慢尝试根据第二个表中的行在一个表中查找 "missing"记录

标签 mysql sql

背景:

电子商务网络应用程序,但具有相互订购的“成员”。当成员执行各种事件(例如搜索)时,记录将插入到“事件”表中。如果/当成员(member)提交订单时,一条记录将被插入到“订单”表中。目标是找到成员(member)执行事件但在事件时间后的某个时间窗口(比如一个小时)内没有下订单的情况。

注意:创建订单记录的代码不能更改。如果可能的话,我可以简单地“记住”这些事件,并将此信息包含在订单记录中。然后,查找成员执行事件但未订购的情况很简单:只需在订单表的这一列中查找 NULL 值(或其他一些默认值)。再次,唉,这在我的情况下是不可能的......

表格:

  • Order (id, ts/* timestamp */, sending_member_id, receiving_member_id, …)
  • 成员(id,姓名,...)
  • Activity_Type(ID、名称……)
  • Activity_Log(id、ts、member_id、type_id、extra_info)

索引:

All appropriate indexes are in place. Specifically, an index on order.ts does exist.

我试过这三个查询:

方法一

SELECT …
  FROM activity_log, 
       Member
 WHERE activity_log.member_id = member.id
   AND activity_log.type_id = 1 /* Search */
   AND activity_log.ts > [start time]
   AND activity_log.ts < [end time]
   AND NOT EXISTS (SELECT ‘x’
                     FROM order
                    WHERE order.ts >= activity_log.ts
                      AND order.ts <= activity_log.ts + 3600
                      AND order.sending_member_id = activity_log.member_id)
ORDER BY activity_log.member_id, activity_log.ts desc

方法二

SELECT …
  FROM activity_log, member
 WHERE activity_log.member_id = member.id
   AND activity_log.type_id = 1 /* Search */
   AND activity_log.ts > [start time]
   AND activity_log.ts < [end time]
   AND activity_log.member_id NOT IN (SELECT order.sending_member_id
                                        FROM order
                                       WHERE order.ts >= activity_log.ts
                                         AND order.ts <= activity_log.ts + 3600)
ORDER BY activity_log.member_id, activity_log.ts desc

方法 3

   SELECT …
     FROM activity_log
     JOIN member ON activity_log.member_id = member.id
LEFT JOIN order ON order.ts >= activity_log.ts 
               AND order.ts <= activity_log.ts + 3600 
               AND activity_log.member_id = order.sending_member_id
    WHERE activity_log.type_id = 1 /* Search */
      AND activity_log.ts > [start time]
      AND activity_log.ts < [end time]
      AND order.sending_member_id IS NULL
 ORDER BY activity_log.member_id, activity_log.ts desc

即使使用方法 3,查询也会运行 20-30 秒并且不使用 order.ts 上的索引。

最佳答案

对于 MySQL,选择取决于被比较的列:

如果您更改数据以进行比较,索引将毫无用处:

AND order.ts <= activity_log.ts + 3600 

在此示例中,ACTIVITY_LOG.ts 上的索引无关紧要。考虑复合索引(单个索引,多列)。

关于mysql 查询缓慢尝试根据第二个表中的行在一个表中查找 "missing"记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6039166/

相关文章:

php - 如何在 while 循环中显示数据库中的 BLOB 图像

mysql - 在laravel中获取除0之外的最小值

php - 如何更改显示顺序?

用于在存储过程中查找和替换文本的 SQL 查询

sql - 在 postgres 中计算表大小的正确方法是什么?

mysql - 从内连接创建表非常慢

android - 这种从sqlite获取数据的方式正确吗?

SQL:为每个填充的列选择多行

MySQL 日期有效性

mysql - 选择共享 MIN(PRICE) 值的多个书名 | MySQL