Oracle SQL:子查询与Order By Fetch First 1 Row Only效率对比
两种Oracle SQL查询的执行效率对比
我们有一张超500万条数据的审计表(结构及样例数据如下),需求是获取REF_NO为'Dummy2'的记录中ID最大的那条的薪资(即Dummy2的最新薪资),以下是两种查询语句,我们来对比它们的执行效率:
| ID | REF_NO | NAME | SALARY |
|---|---|---|---|
| 1 | Dummy1 | Smith | 5487 |
| 2 | Dummy2 | Tim | 3123 |
| 3 | Dummy1 | Smith | 432424 |
| 4 | Dummy4 | Steve | 99577 |
| 5 | Dummy5 | Matt | 5551444 |
| 6 | Dummy2 | Tim | 432112 |
| 7 | Dummy7 | Brad | 89897 |
| 8 | Dummy3 | Kevin | 123213 |
| 9 | Dummy3 | Kevin | 7878 |
| 10 | Dummy3 | Kevin | 43555 |
| 11 | Dummy2 | Tim | 432 |
| 12 | Dummy8 | Jerry | 32123 |
| 13 | Dummy8 | Jerry | 43434 |
| 14 | Dummy9 | Gayle | 8989897 |
| 15 | Dummy2 | Tim | 1234 |
| 16 | Dummy6 | Jeff | 8989987 |
| 17 | Dummy1 | Smith | 545453 |
| 18 | Dummy2 | Tim | 6464 |
| 19 | Dummy2 | Tim | 43535 |
| 20 | Dummy1 | Smith | 64643 |
| 21 | Dummy8 | Jerry | 995 |
查询语句1
select a.Name, a.Salary from table a where a.REF_NO = 'Dummy2' and a.ID = (select max(id) from table where REF_NO = a.REF_NO)
查询语句2
select Name, Salary from table where REF_NO = 'Dummy2' order by ID desc fetch first row only
执行效率对比
在Oracle中,查询语句2的执行效率更高,原因如下:
- 查询逻辑层面:
查询1是关联子查询,对于每个满足REF_NO='Dummy2'的记录,都会触发一次子查询获取该REF_NO对应的最大ID,即便Oracle有优化,500万级数据下重复执行子查询的开销也会很明显;而查询2先过滤出目标REF_NO的所有记录,再按ID降序取第一条,逻辑更简洁直接。 - 索引利用层面:
如果创建了复合索引(REF_NO, ID DESC, SALARY, NAME),查询2可以直接通过索引定位到符合条件的第一条记录,无需回表、无需额外排序(索引本身已按ID降序排列),一次索引扫描就能完成;查询1即便用同样索引,子查询虽能快速取到最大ID,但外层还要做ID匹配,步骤比查询2繁琐。 - 执行计划角度:
查询2的执行计划通常是「索引范围扫描(按REF_NO过滤)→ 直接取第一条记录」,ORDER BY会被索引优化掉;查询1的执行计划要么是外层扫描每条匹配记录触发子查询,要么是合并子查询后做关联判断,整体复杂度高于查询2。
总结:在大数量级数据场景下,查询2的执行效率明显优于查询1,尤其是有合适索引加持时,差距会更显著。
内容的提问来源于stack exchange,提问作者Intekhab Alam
相关产品推荐
相关产品推荐

