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

1 篇文章 0 订阅
1 篇文章 0 订阅

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

 

表结构如下: 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

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

 

       

   Reply    18355   22 小时 56 分钟前   ♥ 1

我认为应该是 1

 

       

   Reply    2ckaiii   22 小时 49 分钟前   ♥ 1

1

 

       

   Reply    3luoyou1014   22 小时 47 分钟前   ♥ 2

亲,你有数据直接到数据库里面执行 sql 验证下,比我们验证快多了。。。

 

       

   Reply    4kisshere   22 小时 39 分钟前

如果 2 很有用的情况,还发明 MAX 函数搞啥,所以,我站 1

 

       

   Reply    5linbiaye   22 小时 25 分钟前

mysql 肯定是 1 了

 

       

   Reply    6glacer   22 小时 22 分钟前   ♥ 4

在存在(uid, rid)索引的情况下,rid 会按索引排序,两条语句的性能应该是接近的。
如果没有索引,个人认为是 1,原因是 Max 函数取最大值的复杂度为 O(n),而排序的复杂度通常为 O(nlogn)。因此 max 函数的复杂度会低一些。

 

       

   Reply    7ljpCN   21 小时 48 分钟前 via Android

一个是最大值,一个是排序,我想除非实现的人抽风了,不然明显最大值的复杂度只有 O(n)

 

       

   Reply    8enenaaa   21 小时 47 分钟前

一样的 ,TOP 1 也是 O(n)

 

       

   Reply    9zjp   21 小时 47 分钟前 via Android

PostgreSQL 的 explain 很强大,别浪费。
另外按照语义写就是 1

 

       

   Reply    10dog82   21 小时 24 分钟前

差不多一样,但是 1 明显更易懂!

 

       

   Reply    11godlovesxcjtest   21 小时 14 分钟前 via Android

排序和求最大值复杂度会一样?一个是 O(N2),一个是 On,所以不是很明显吗

 

       

   Reply    12sanggao   21 小时 4 分钟前 via iPhone   ♥ 1

我的天那,看了楼上几个回复!!!!

 

       

   Reply    13no1xsyzy   20 小时 53 分钟前

SQL 的优化是数据库帮你完成的,不同的实现可能不同,不过我认为至少存在一个数据库软件这两者是等价的,甚至你写 2 都直接给你优化成 1 实现。
那么,谁来试一下 PostgreSQL 的优化是否包含 ORDER DESC LIMIT 1 == Max ?
不过如果没有该优化应该选 1 ;同时为了语义也应该选 1。我看不到选 2 的情况。

 

       

   Reply    14CEBBCAT   20 小时 40 分钟前 via Android

@sanggao 老哥快别吊胃口了,说说楼上哪里有问题吧

 

       

   Reply    15littlewing   20 小时 37 分钟前

我的天那,看了楼上几个回复!!!!

 

       

   Reply    16no1xsyzy   20 小时 33 分钟前   ♥ 1

就当我口胡吧,似乎两者功能不完全等价。
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 效率极高。

如果有索引我认为两者基本一致,因为不会需要进行一次排序。

 

       

   Reply    17no1xsyzy   20 小时 27 分钟前

@no1xsyzy 好像建立了索引还是,刚没细读,搜不出来的情况 ORDER BY DESC + LIMIT 1 时间很长,用了 JOIN 就 1200ms 以上,写成子查询才保持始终最短时间。
综上,A/B 测试吧。

 

       

   Reply    18imherer   20 小时 23 分钟前

@glacer 确实是,我往表里插了 100W 数据,有(uid, rid)索引的情况下确实是一样的,差不多都是 38ms 左右

 

       

   Reply    19526353781   20 小时 18 分钟前

看联合索引顺序
如果是 rid 是左边那么用得着索引,如果在 MySQL innodb 里面索引默认就有顺序,所以不需要重复的排序这个过程
我不清楚 max 里面的排序过程,但是不管怎样,语句二都不用排序了这么都比 1 性能更优吧

所以
1. 如果联合索引 rid,uid 语句 2 最优
2. 建议设置主键索引,如果没有主键索引 innodb 内部也会帮你建立一个内部的,毕竟数据是放聚簇上的

 

       

   Reply    20c4f36e5766583218   20 小时 1 分钟前

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 的本意。

 

       

   Reply    21carlclone   19 小时 40 分钟前

感觉是一样的 , uid 确认的情况下 rid 是有序的 , 并不需要再排序

 

       

   Reply    22polymerdg   17 小时 43 分钟前

MYSQL 第一种

 

       

   Reply    23MetoYou   17 小时 37 分钟前

有索引能命中应该是一样的,没索引应该是 1 快

 

       

   Reply    24Aruforce   17 小时 26 分钟前

UID,RID 联合索引应该是有顺序的...
大概类似于..这个结构
```
BPTree{
NODE uid; //uid 里面有一个 RID 的系列节点 array []形式?。。而这些节点是在插入时就排好序的...
}
```
这个两种实现速度上应该没什么区别才对...

1 的更容易看出意思来...

 

       

   Reply    25javlib   14 小时 36 分钟前 via Android

用 explain 看看呢? pg 的 explain 应该可以给出优化后的执行 plan

 

隐藏       感谢回复者

   Reply    26maierhuang   10 小时 42 分钟前

一个字段上有索引的情况下两种执行计划是一致的,如果是无索引(或则楼主这种联合索引 rid 在后的情况下),max ( rid )走全表扫描,order by 这种需要 sort。

 

       

   Reply    27leishi1313   9 小时 43 分钟前 via Android

与其盲猜,不如用 EXPLAIN ANALYZE 在表上跑一下不就知道了嘛

 

       

   Reply    28applehater   9 小时 17 分钟前

怎么禁用缓存?

 

       

   Reply    29Iamnotfish   5 小时 42 分钟前

哈,这个楼主如果用的是 SQL 的话我刚测过。160W 条数据,用 MAX 的话是比 DESC LIMIT 1 要快的,大概快十几 MS,不过不确定是不是因为有缓存了才是这样的结果。

 

       

   Reply    30wd   3 小时 39 分钟前 via iPhone

where 部分过滤之后,后续的动作不就是那 10 条记录的操作了么,这有啥好比的。

 

       

   Reply    31gavinjou818   5 分钟前 via iPhone

我感觉都差不多,假如要纠结...是不是 limit1 多了一个操作

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值