请问在Oracle中取第10条记录到第20条记录,效率最高的SQL语句怎么写?

本文介绍了MySQL中Limit语句在不同场景下的性能表现,并通过实验对比了直接使用Limit与先获取ID再使用Limit的方式,得出了针对不同偏移量大小的最优查询方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


oracle

select * from table where rownum<20
minus
select * from table where rownum<10

//但这种查询的效率更高于前者 (556436条数据,测试结果)
select * from (select rownum r,a.* from blog a where rownum<=20) where r>=10;


mysql> SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15

//为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1:
mysql> SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.

//如果只给定一个参数,它表示返回最大的记录行数目:
mysql> SELECT * FROM table LIMIT 5; //检索前 5 个记录行

//换句话说,LIMIT n 等价于 LIMIT 0,n


mysql limit查询优化[转载],由于limit经常用到,却没有注意,因为平时做的项目都比较小,所以也没有考虑去怎么优化,今天看了一篇关于mysql limit优化的文章,感觉很好 于是转载过来

原文地址在这里
http://www.phpobject.net/blog/read.php?119

MYSQL的优化是非常重要的。其他最常用也最需要优化的就是limit。mysql的limit给分页带来了极大的方便,但数据量一大的时候,limit的性能就急剧下降。
同样是取10条数据

select * from yanxue8_visit limit 10000,10 和



select * from yanxue8_visit limit 0,10


就不是一个数量级别的。

网上也很多关于limit的五条优化准则,都是翻译自mysql手册,虽然正确但不实用。今天发现一篇文章写了些关于limit优化的,很不错。原文地址:http://www.zhenhua.org/article.asp?id=200

文中不是直接使用limit,而是首先获取到offset的id然后直接使用limit size来获取数据。根据他的数据,明显要好于直接使用limit。这里我具体使用数据分两种情况进行测试。(测试环境win2033+p4双核 (3GHZ) +4G内存 mysql 5.0.19)

1、offset比较小的时候。

select * from yanxue8_visit limit 10,10


多次运行,时间保持在0.0004-0.0005之间

Select * From yanxue8_visit Where vid >=(

Select vid From yanxue8_visit Order By vid limit 10,1

) limit 10


多次运行,时间保持在0.0005-0.0006之间,主要是0.0006
结论:偏移offset较小的时候,直接使用limit较优。这个显然是子查询的原因。


2、offset大的时候。

select * from yanxue8_visit limit 10000,10


多次运行,时间保持在0.0187左右

Select * From yanxue8_visit Where vid >=(

Select vid From yanxue8_visit Order By vid limit 10000,1

) limit 10


多次运行,时间保持在0.0061左右,只有前者的1/3。可以预计offset越大,后者越优。

以后要注意改正自己的limit语句,优化一下mysql了

<think>好的,我现在需要帮用户解决在达梦数据库中如何实现查询第11到第20记录的分页问题。首先,我得回忆一下达梦数据库的特点,以及它支持的分页方法。用户之前问过关于SQL更新语句的问题,现在转向分页查询,说明他们可能在处理数据展示或报表需求,需要分页来优化性能或用户界面。 首先,达梦数据库是基于SQL标准的,所以可能需要使用常见的分页方法,比如使用LIMIT和OFFSET,或者ROW_NUMBER()窗口函数。不过,不同的数据库系统语法可能有所不同,比如Oracle用ROWNUM,而MySQL用LIMIT。达梦可能也有自己的特定语法。 用户提到的是查询第11到第20记录,也就是每页10,第二页的数据。常见的分页策略是跳过前10接下来的10。在标准SQL中,可以使用OFFSET 10 LIMIT 10,但需要确认达梦是否支持这种语法。 接下来,我需要查阅达梦数据库的官方文档,确认其分页机制。根据之前的经验,达梦可能支持类似MySQL的LIMIT语法,或者像Oracle那样使用子查询和ROWNUM。另外,达梦可能也支持ROW_NUMBER()函数来实现分页。 假设达梦不支持LIMIT和OFFSET,那么可能需要使用ROW_NUMBER()函数,给每一行分配一个行号,然后根据行号筛选。例如: SELECT * FROM ( SELECT t.*, ROW_NUMBER() OVER (ORDER BY 某列) AS rn FROM 表名 t ) WHERE rn BETWEEN 11 AND 20; 不过,这里的排序字段需要用户指定,否则结果可能不稳定。用户可能没有指定排序,这时候需要提醒他们必须使用ORDER BY来保证分页的正确性。 另外,达梦可能有自己的分页扩展语法,比如TOP或者FETCH,类似SQL Server。例如,使用OFFSET FETCH子句: SELECT * FROM 表名 ORDER BY 某列 OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY; 如果达梦支持这种语法,那么这就是最简洁的方式。但需要确认是否兼容。 还有一种方法是使用子查询和ROWNUM,类似Oracle的做法: SELECT * FROM ( SELECT t.*, ROWNUM AS rn FROM ( SELECT * FROM 表名 ORDER BY 某列 ) t WHERE ROWNUM <= 20 ) WHERE rn >= 11; 但达梦是否使用ROWNUM关键字呢?可能需要确认。 现在,我需要综合这些可能性,给出达梦数据库适用的分页方法。根据之前的知识,达梦数据库通常兼容Oracle的语法,所以可能支持ROWNUM的方式,同时也可能支持OFFSET FETCH。 但用户需要的是第11到20,所以无论哪种方法,都需要确保正确的排序和范围选择。同时,必须强调ORDER BY的重要性,否则分页结果可能不一致。 另外,用户可能没有提到排序字段,这时候可能需要提醒他们,分页必须结合排序才有意义,否则数据的顺序可能不稳定,导致分页结果重复或遗漏。 最后,可能需要给出两种方法:一种是使用ROW_NUMBER()函数,另一种是使用OFFSET FETCH(如果支持),并说明各自的优缺点。同时,提醒事务和性能问题,比如大数据量下的分页效率,可能需要优化查询或使用索引。 总结下来,回答的结构应包括: 1. 分页的必要件:排序字段,确保结果顺序稳定。 2. 使用ROW_NUMBER()的示例。 3. 使用OFFSET FETCH的示例(如果适用)。 4. 兼容不同版本的注意事项。 5. 性能优化建议。</think>--- ### **达梦数据库分页查询实现方法** 在达梦数据库(DM Database)中,实现查询第 **11 到 20 记录**的分页操作,需结合 **窗口函数** 或 **LIMIT/OFFSET** 语法(根据版本支持情况)。以下是具体实现方案: --- ### **1. 使用 `ROW_NUMBER()` 窗口函数(通用方法)** 适用于所有支持窗口函数的数据库版本,兼容性强且逻辑清晰。 ```sql SELECT * FROM ( SELECT t.*, ROW_NUMBER() OVER (ORDER BY 排序列) AS rn -- 必须指定排序字段 FROM 表名 t ) tmp WHERE rn BETWEEN 11 AND 20; ``` #### **关键点** - **必须指定排序字段**(如 `ORDER BY id` 或 `ORDER BY create_time`),否则分页结果可能不稳定。 - `rn BETWEEN 11 AND 20` 表示第 11 到第 20 记录。 --- ### **2. 使用 `LIMIT ... OFFSET` 语法(DM 8+ 版本支持)** 达梦 **8.0 及以上版本** 支持类似 MySQL 的 `LIMIT` 分页语法,法更简洁。 ```sql SELECT * FROM 表名 ORDER BY 排序列 -- 必须指定排序 LIMIT 10 OFFSET 10; -- 跳过前10接下来的10(即第11~20) ``` #### **参数说明** - `LIMIT 10`:每页返回 10 。 - `OFFSET 10`:跳过前 10 记录(从第 11 开始)。 --- ### **3. 兼容低版本的替代方案(使用子查询)** 若数据库版本较低,可通过子查询和 `ROWNUM` 模拟分页: ```sql SELECT * FROM ( SELECT t.*, ROWNUM AS rn -- 达梦兼容 Oracle 的 ROWNUM 伪列 FROM ( SELECT * FROM 表名 ORDER BY 排序列 -- 内层确保排序 ) t WHERE ROWNUM <= 20 -- 控制上限 ) WHERE rn >= 11; -- 控制下限 ``` --- ### **注意事项** 1. **必须指定排序字段** 分页查询需依赖稳定的排序结果,否则多次查询可能出现重复或遗漏。 2. **性能优化** - 对 `排序列` 建立索引,避免全表扫描。 - 避免深度分页(如 `OFFSET 100000`),建议改用 `WHERE id > 末ID` 的分页方式。 3. **达梦版本差异** - **DM 7 及以下**:推荐使用 `ROW_NUMBER()` 或子查询方案。 - **DM 8+**:优先使用 `LIMIT/OFFSET` 语法。 --- ### **示例:查询 `employee` 表的第11~20记录** 假设按 `employee_id` 升序分页: ```sql -- 方法1:ROW_NUMBER() SELECT * FROM ( SELECT e.*, ROW_NUMBER() OVER (ORDER BY employee_id) AS rn FROM employee e ) tmp WHERE rn BETWEEN 11 AND 20; -- 方法2:LIMIT/OFFSET(DM 8+) SELECT * FROM employee ORDER BY employee_id LIMIT 10 OFFSET 10; ``` --- ### **总结** - **核心逻辑**:通过排序确定记录顺序,按范围截目标数据。 - **推荐方案**:达梦 8+ 使用 `LIMIT/OFFSET`,低版本使用 `ROW_NUMBER()`。 - **稳定性**:务必指定排序字段,避免分页结果混乱。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值