MySQL:按查询分组优化

MySQL:按查询分组优化,mysql,group-by,query-optimization,greatest-n-per-group,groupwise-maximum,Mysql,Group By,Query Optimization,Greatest N Per Group,Groupwise Maximum,我得到了以下模式的表: +----+--------+----------------------------+----------------------------+ | id | amount | created_timestamp | updated_timestamp | +----+--------+----------------------------+----------------------------+ | 1 | 1.00 |

我得到了以下模式的表:

+----+--------+----------------------------+----------------------------+
| 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
groupby
having
编写了以下查询,但它不起作用。有人能帮忙吗

select id, any_value(`updated_timestamp`), any_value(amount) from transactions group by `id` having max(`updated_timestamp`);
在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\u timestamp)
上建立一个复合索引。对
id
updated\u时间戳
有单独的索引是不等效的

为什么选择综合指数? 请注意,索引只是表中数据的副本。在许多方面,它的工作原理与表相同。因此,创建索引就是创建表数据的副本,RDBMS可以使用该副本以更高效的方式查询表信息

updated_timestamp
上的索引将创建包含
updated_timestamp
作为第一列的数据副本,并且该数据将被排序。它还将在每个索引行中包含一个隐藏的行ID值(将用作主键),以便它可以使用该值查找实际表中的整行

这对这个查询(任何一个版本)有什么帮助?如果我们只需要最新(或最早)的
updated\u timestamp
总的来说,它会有所帮助,因为它可以检查索引中的第一条或最后一条记录。但是,由于我们需要每个
id
的最新索引,因此该索引是无用的

只在
id
上建立一个索引怎么样。这里我们有一个
id
列的副本,按
id
列排序,行id附加到索引中的每一行

这对查询有什么帮助?它没有,因为它甚至没有<代码>更新的时间戳< /代码>列作为索引的一部分,所以甚至不考虑使用这个索引。< /P>

现在,考虑一个复合索引:<代码>(ID,UpDestEdTimeType).P/> 这将创建一个数据副本,首先使用

id
列进行排序,然后还包括第二列
updated\u timestamp
,并在每个
id
中进行排序

这与电话簿(如果人们仍然将这些东西用作镇纸以外的东西)按姓和名排序的方式相同

因为行是以这种方式排序的,所以MySQL可以为每个
id
查找给定
id
的最后一条记录。它知道该记录包含最高的
updated_timestamp
值,因为索引是如何定义的

因此,它只需为存在的每个
id
查找一行。那很快。进一步解释为什么会占用更多的空间,但如果您愿意,您可以自己研究,只需查看B树即可。可以说,找到第一条(或最后一条)记录很容易

请尝试以下操作:

ALTER TABLE transactions
ADD INDEX `LatestTransaction` (`id`,`updated_timestamp`)
然后查看您的原始查询或我的备用查询是否更快。很可能两者都比没有索引更快。随着表的增长或select语句的更改,它可能会影响这些查询中哪一个更快,但无论使用哪一版本的查询,索引都将提供最大的性能提升。

在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\u timestamp)
上建立一个复合索引。对
id
updated\u时间戳
有单独的索引是不等效的

为什么选择综合指数? 请注意,索引只是表中数据的副本。在许多方面,它的工作原理与表相同。因此,创建索引就是创建表数据的副本,RDBMS可以使用该副本以更高效的方式查询表信息

updated_timestamp
上的索引将创建包含
updated_timestamp
作为第一列的数据副本,并且该数据将被排序。它还将在每个索引行中包含一个隐藏的行ID值(将用作主键),以便它可以使用该值查找实际表中的整行

这对这个查询(任何一个版本)有什么帮助?如果我们只需要最新(或最早)的
updated\u timestamp
总的来说,它会有所帮助,因为它可以检查索引中的第一条或最后一条记录。但是,由于我们需要每个
id
的最新索引,因此该索引是无用的

只在
id
上建立一个索引怎么样。这里我们有一个
id
列的副本,按
id
列排序,行id附加到索引中的每一行

这对查询有什么帮助?它没有,因为它甚至没有<代码>更新的时间戳< /代码>列作为索引的一部分,所以甚至不考虑使用这个索引。< /P>

现在,考虑一个复合索引:<代码>(ID,UpDestEdTimeType).P/> 这将首先使用

id
列创建数据副本,并对其进行排序,然后还包括第二列
updated\u timestamp
,并且