下面两条 SQL 语句哪个效率更高?

2019-06-24 11:08:49 +08:00
 imherer

表结构如下: uid,rid,name,home,event,data,time

其中 uid 和 rid 联合唯一索引

假如现在表里有接近 100W 行数据,其中每个 uid 大概有 10 行记录

现要查询出单个 uid 下的最大 rid,下面哪个 SQL 语句效率更高呢?

1.SELECT MAX(rid) AS rid FROM table WHERE uid = $1

2.SELECT rid FROM table WHERE uid = $1 ORDER BY rid DESC LIMIT 1

数据库为:PostgreSQL

另外像这样的表结构没有主键性能上会有什么问题吗?(因为主键是用不到的)

8657 次点击
所在节点    PostgreSQL
34 条回复
8355
2019-06-24 11:16:02 +08:00
我认为应该是 1
ckaiii
2019-06-24 11:23:21 +08:00
1
luoyou1014
2019-06-24 11:25:42 +08:00
亲,你有数据直接到数据库里面执行 sql 验证下,比我们验证快多了。。。
kisshere
2019-06-24 11:33:13 +08:00
如果 2 很有用的情况,还发明 MAX 函数搞啥,所以,我站 1
linbiaye
2019-06-24 11:47:55 +08:00
mysql 肯定是 1 了
glacer
2019-06-24 11:50:53 +08:00
在存在(uid, rid)索引的情况下,rid 会按索引排序,两条语句的性能应该是接近的。
如果没有索引,个人认为是 1,原因是 Max 函数取最大值的复杂度为 O(n),而排序的复杂度通常为 O(nlogn)。因此 max 函数的复杂度会低一些。
ljpCN
2019-06-24 12:24:42 +08:00
一个是最大值,一个是排序,我想除非实现的人抽风了,不然明显最大值的复杂度只有 O(n)
enenaaa
2019-06-24 12:25:35 +08:00
一样的 ,TOP 1 也是 O(n)
zjp
2019-06-24 12:25:56 +08:00
PostgreSQL 的 explain 很强大,别浪费。
另外按照语义写就是 1
dog82
2019-06-24 12:48:27 +08:00
差不多一样,但是 1 明显更易懂!
godlovesxcjtest
2019-06-24 12:58:33 +08:00
排序和求最大值复杂度会一样?一个是 O(N2),一个是 On,所以不是很明显吗
sanggao
2019-06-24 13:08:52 +08:00
我的天那,看了楼上几个回复!!!!
no1xsyzy
2019-06-24 13:19:01 +08:00
SQL 的优化是数据库帮你完成的,不同的实现可能不同,不过我认为至少存在一个数据库软件这两者是等价的,甚至你写 2 都直接给你优化成 1 实现。
那么,谁来试一下 PostgreSQL 的优化是否包含 ORDER DESC LIMIT 1 == Max ?
不过如果没有该优化应该选 1 ;同时为了语义也应该选 1。我看不到选 2 的情况。
CEBBCAT
2019-06-24 13:32:13 +08:00
@sanggao 老哥快别吊胃口了,说说楼上哪里有问题吧
littlewing
2019-06-24 13:35:01 +08:00
我的天那,看了楼上几个回复!!!!
no1xsyzy
2019-06-24 13:39:05 +08:00
就当我口胡吧,似乎两者功能不完全等价。
https://stackoverflow.com/questions/34246403/performance-of-max-vs-order-by-desc-limit-1
ORDER BY DESC 会导致 NULL 在最前,所以有 NULL 的时候 2. 选出来的那个一定是 NULL。

而该提问应该是没有索引导致的问题,而根据是否能选出至少一行(有 WHERE 所以不一定能找出来):
找得出来的情况 ORDER BY DESC + LIMIT 1 效率比 MAX 高;
找不出来的情况 MAX 效率极高。

如果有索引我认为两者基本一致,因为不会需要进行一次排序。
no1xsyzy
2019-06-24 13:45:18 +08:00
@no1xsyzy 好像建立了索引还是,刚没细读,搜不出来的情况 ORDER BY DESC + LIMIT 1 时间很长,用了 JOIN 就 1200ms 以上,写成子查询才保持始终最短时间。
综上,A/B 测试吧。
imherer
2019-06-24 13:49:07 +08:00
@glacer 确实是,我往表里插了 100W 数据,有(uid, rid)索引的情况下确实是一样的,差不多都是 38ms 左右
WriteCloser
2019-06-24 13:54:57 +08:00
看联合索引顺序
如果是 rid 是左边那么用得着索引,如果在 MySQL innodb 里面索引默认就有顺序,所以不需要重复的排序这个过程
我不清楚 max 里面的排序过程,但是不管怎样,语句二都不用排序了这么都比 1 性能更优吧

所以
1. 如果联合索引 rid,uid 语句 2 最优
2. 建议设置主键索引,如果没有主键索引 innodb 内部也会帮你建立一个内部的,毕竟数据是放聚簇上的
c4f36e5766583218
2019-06-24 14:11:03 +08:00
1. 取某一列的最大值,最小值
min/max vs order by: https://stackoverflow.com/questions/426731/min-max-vs-order-by-and-limit
2. 取某一列值,移除重复项
DISTINCT vs GROUP BY: https://blog.csdn.net/ljl890705/article/details/70602442
我觉得吧,看你需求,如果只是简单的取最大 /小值或者去重,还是用原生函数较好。毕竟不是 order-by,group-by 的本意。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/576842

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX