mysql:按查询分组优化

nnt7mjpx  于 2021-06-25  发布在  Mysql
关注(0)|答案(1)|浏览(294)

我得到了一个包含以下模式的表:

+----+--------+----------------------------+----------------------------+
| id | amount | created_timestamp          | updated_timestamp          |
+----+--------+----------------------------+----------------------------+
| 1  |   1.00 | 2018-01-09 12:42:38.973222 | 2018-01-09 12:42:38.973222 |
+----+--------+----------------------------+----------------------------+

来,给你 id = 1 ,可以有多个金额条目。我想提取最后添加的条目及其相应的数量,按id分组。
我在self表上编写了一个具有内部联接的工作查询,如下所示:

SELECT t1.id, 
       t1.amount, 
       t1.created_timestamp, 
       t1.updated_timestamp 
FROM   transactions AS t1 
       INNER JOIN (SELECT id, 
                          Max(updated_timestamp) AS last_transaction_time 
                   FROM   transactions 
                   GROUP  BY id) AS latest_transactions 
               ON latest_transactions.id = t1.id 
                  AND latest_transactions.last_transaction_time = 
                      t1.updated_timestamp;

我认为内部连接是一种过度杀伤力,可以用更优化/更高效的查询来代替。我已经用编写了以下查询 where , group by ,和 having 但它不起作用。有人能帮忙吗?

select id, any_value(`updated_timestamp`), any_value(amount) from transactions group by `id` having max(`updated_timestamp`);
idv4meu8

idv4meu81#

在mysql中执行这样的查询时,有两个(好的)选项。您已经尝试了一个选项。另一个是:

SELECT t1.id, 
       t1.amount, 
       t1.created_timestamp, 
       t1.updated_timestamp 
FROM   transactions AS t1 
LEFT OUTER JOIN transactions later_transactions
       ON later_transactions.id = t1.id 
       AND later_transactions.last_transaction_time > t1.updated_timestamp
WHERE  later_transactions.id IS NULL

这些方法是文档中的方法,也是我基本上每天在工作中使用的方法。哪一个效率最高取决于多种因素,但通常情况下,如果一个慢,另一个就会快。
另外,正如草莓在评论中指出的,你需要一个关于 (id,updated_timestamp) . 有单独的索引 id 以及 updated_timestamp 不是等价的。

为什么是综合指数?

请注意,索引只是表中数据的副本。在许多方面,它的工作原理与表相同。因此,创建索引就是创建表数据的副本,rdbms可以使用该副本以更高效的方式查询表信息。
一个索引 updated_timestamp 将创建包含 updated_timestamp 作为第一列,该数据将被排序。它还将在每个索引行中包含一个隐藏的行id值(作为主键),以便它可以使用该值在实际表中查找整行。
这在这个查询中有什么帮助(任何一个版本)?如果我们只想要最新的(或最早的) updated_timestamp 总的来说,它会有所帮助,因为它可以检查索引中的第一个或最后一个记录。但既然我们每个人都想要最新的 id ,此索引无效。
只是一个索引怎么样 id . 我们有一份 id 列,按 id 列,行id附加到索引中的每一行。
这对查询有什么帮助?它没有,因为它甚至没有 updated_timestamp 列作为索引的一部分,因此甚至不会考虑使用此索引。
现在,考虑一个综合指数: (id,updated_timestamp) .
这将使用 id 列,排序,然后是第二列 updated_timestamp 也包括在内,并且在每个 id .
这与电话簿(如果人们仍将这些东西用作镇纸以外的东西)按姓氏和名字排序的方式相同。
因为行是这样排序的,所以mysql可以为每一行 id ,在给定的 id . 它知道那个记录包含了最高的 updated_timestamp 值,因为索引是如何定义的。
所以,它只需要为每一行查找一行 id 那是存在的。太快了。进一步解释为什么会占用更多的空间,但如果你愿意,你可以自己研究,只要看看b-树。可以说,找到第一个(或最后一个)记录很容易。
请尝试以下操作:

ALTER TABLE transactions
ADD INDEX `LatestTransaction` (`id`,`updated_timestamp`)

然后看看您的原始查询还是我的备用查询速度更快。很可能两者都比没有索引要快。随着表的增长,或者select语句的更改,它可能会影响这些查询中哪个更快,但是索引将提供最大的性能提升,而不管您使用哪个版本的查询。

相关问题