【问题标题】:How do I properly index a query that selects multiple fields when using GROUP BY and ORDER BY?使用 GROUP BY 和 ORDER BY 时,如何正确索引选择多个字段的查询?
【发布时间】:2013-08-28 13:09:59
【问题描述】:

我的问题

我们有一个电子邮件引擎,它可以以块的形式(向多个用户发送相同的电子邮件:即批量通讯)或单个案例(向一个用户发送一封电子邮件:即,重置密码)向用户发送电子邮件。我们有一个管理控制台,它显示已发送电子邮件的日志。

目前,该表大约有 750,000 行。对于发送的每个 EMAIL,表中都会记录以下内容(精简到主要项目):

  • 身份证
  • batch_id
  • user_id
  • 主题
  • 发送日期
  • 已创建

如果发送了一批电子邮件,则该批中的所有电子邮件都将具有相同的batch_id。当管理员浏览日志控制台时,我们不想在表格结果中显示来自批次的所有电子邮件 - 只是一个唯一的。所以我们这样做了:

SELECT id, batch_id, user_id, subject, send_date, created FROM `emails` 
GROUP BY batch_id
ORDER BY created DESC
limit 10

这可行,但速度很慢。这是我们对查询的 EXPLAIN 的结果:

+----+-------------+-------------+-------+---------------+----------+---------+------+------+---------------------------------+
| id | select_type | table       | type  | possible_keys | key      | key_len | ref  | rows | Extra                           |
+----+-------------+-------------+-------+---------------+----------+---------+------+------+---------------------------------+
|  1 | SIMPLE      | emails_logs | index | NULL          | batch_id | 17      | NULL | 2522 | Using temporary; Using filesort |
+----+-------------+-------------+-------+---------------+----------+---------+------+------+---------------------------------+
1 row in set (0.00 sec)

我们的目标

快速选择batch_id 的唯一记录,按记录创建日期降序排列。

我的问题是:如何以最佳方式索引这些,并以适当的方式选择字段以利用这些索引?

谢谢!

【问题讨论】:

  • 请不要使用 MySQL 的GROUP BY extension
  • 好的,请详细说明为什么?还是提出可行的解决方案?
  • 我建议阅读文档。您正在此处寻找DISTINCT 结果集。
  • 我没有选择 DISTINCT 行,只是排除了具有相同 batch_id 的记录
  • 然后使用HAVING COUNT(batch_id) < 2

标签: mysql sql indexing group-by sql-order-by


【解决方案1】:

这是一个想法。在emails(created, batchid) 上创建一个索引,在emails(batchid) 上创建另一个索引。现在做:

select e.id, e.batch_id, e.user_id, e.subject, e.send_date, e.created
from (select batchid, created
      from emails
      order by created desc
      limit 10
     ) e10 join
     emails e
     on e.batchid = e10.batchid
group by e.batchid
order by created desc;

这个想法是在进行聚合和排序之前减少您正在处理的集合。

听起来你的数据如果更规范化会更好。一个表应该有批次信息,包括发件人和创建日期。另一个应该有

【讨论】:

  • 这是一个很好的解决方案,但是在未分组的“重复”记录上调用了子选择中的限制。因此,如果我有一批发送给 50 人的电子邮件,当我进行选择时,它只会返回 1 条记录,而不是我期望的 10 条不同的记录
  • @BarryChapman 。 . .子查询应使用第一个索引来查找最佳批次。第二个索引应该用于连接。使用减少的集合,查询应该运行得更快。
  • 我能够修改它以正确解决我的问题,感谢 Gordon 的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-21
  • 1970-01-01
  • 1970-01-01
  • 2019-01-21
  • 2013-10-23
  • 1970-01-01
相关资源
最近更新 更多