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
,并且