MySQL 查询从 1000 万行表中获取每个条目的最新记录

标签 mysql sql query-optimization greatest-n-per-group

用例:

我有表格,可以说:“制造商

manuf_code  manuf_display_name  record_status  record_timestamp  

----------  -------------------  ------------  ----------------
M000001      Sam                      N        2017-09-13 12:13:16      
M000002      JII                      N        2017-09-13 15:13:15      
M000002      JII                      U        2017-09-13 17:16:35      
M000003      Sun                      N        2017-09-13 18:54:16      
M000004      NG-Graphics              N        2017-09-13 19:13:15
M000004      NG-Graphics              U        2017-09-14 20:16:50 
M000004      NG-Graphics              U        2017-09-14 09:13:25 
M000005      HewNett                  N        2017-09-15 10:24:19     
M000006      HewNett                  N        2017-09-15 10:24:19  
M000007      HewNett                  N        2017-09-15 10:24:19  
M000007      HewNett                  U        2017-09-15 15:10:16 
M000007      HewNett                  U        2017-09-17 21:35:19 
M000007      HewNett                  U        2017-09-17 21:37:26  
  • 当用户创建新制造商时,详细信息位于表中,record_status 为“N”。
  • 当用户更新现有制造商时,该制造商 ID 的行会更新,record_status 为“U

现在大约有 7-1000 万个这样的条目,每个制造商都具有:

  • 状态为“N”的单个条目
  • 状态为“U”的多个条目

要求:我需要获取每个制造商的最新条目。

我的查询:

SELECT m.manuf_code
     , m.manuf_display_name
     , m.record_timestamp
     , m.record_status 
  FROM manufacturers m 
  JOIN
     ( SELECT manuf_code
           , MAX(record_timestamp) AS maxdate 
        FROM manufacturers 
           WHERE record_status = 'N' OR record_status = 'U' 
         GROUP 
          BY manuf_code) mn
    ON m.manuf_code = mn.manuf_code 
   AND m.record_timestamp = mn.maxdate  

我更喜欢 Join 子查询,因为前者速度更快,可获取大约 700 万条数据。

但是,我需要更快地完成这项工作,因为在获取这么多数据后,我什至可能必须使用新的 record_status 在某个表中插入相同的数据。

请提出建议。

编辑:

CREATE TABLE `manufacturers` (
  `manuf_code` varchar(20) NOT NULL,
  `record_status` varchar(1) NOT NULL,
  `manuf_display_name` varchar(50) NOT NULL,
  `record_timestamp` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`manuf_code`, `record_update_timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

说明:

新条目的状态为 --> 'N' 现有条目的更新将具有状态 --> 'U' 就是这样。查询应该是最新的。

另一种情况,具体到要求是,我们获取每条记录的所有最新条目并将状态设置为“L”并再次插入它们

最佳答案

首先解决眼前的问题,然后讨论替代设计:

分组最大值

这是一个“分组最大值”问题。对于数百万行的表,典型的查询相当慢,都涉及全表扫描。要对此进行改进,请参阅 http://mysql.rjweb.org/doc.php/groupwise_max

历史与当前

另一种方法是保留 2 个表:

  • 操作历史记录;这就是你目前拥有的。它主要是插入到。
  • 每个项目的
  • 当前状态。从中获取数据是微不足道的。它主要是更新。或者,更好的是,INSERT...ON DUPLICATE KEY UPDATE... 以便无需额外语句即可插入新项目。

你说“当用户创建/更新......”。这是如何进行的?我希望他们没有发出 SQL 语句。我建议你考虑一些子例程(在客户端代码中)或存储过程(在 MySQL 中)。这样,您就可以向用户隐藏两个表的详细信息等。

批量上传

你说大量的插入/更新/等是集体提供的?将其加载到临时表中(CREATE TEMPORARYTRUNCATE 并重用的永久表)。然后编写相对少量的 SQL 语句将数据组合起来放入Current并铲入(大部分完整)到History`。

关于MySQL 查询从 1000 万行表中获取每个条目的最新记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46211468/

相关文章:

mysql - 谁能帮我看看这个 SQL 查询

MySQL - 从结果中排除所有被阻止的用户

用于特定查询的 MySQL 索引

php - 用于删除数据库中选定行的表单 : displays confirmation always

java - 改进 "search"输入字段的结果?

php - 选择列表菜单回显

hadoop - 在Hive中的许多表上执行有效的联接

sql - Postgres 在 DELETE 时降低触发器性能

php - 如何在 Doctrine query builder 的 'orderBy()' 上使用更高级的参数?

mysql - Django 1.5 查询包含来自其他模型的列