优化
mysql
查询的
limit
参数
我们在做一些查询的时候总希望能避免数据库引擎做全表扫描,因为全表扫描时间长,而且其中大部分扫描对客户端而言是没有意义的。那么在
mysql
中有那些方式是可以避免全表扫面的呢?除了我们大家很熟悉的通过使用索引列或分区等方式来进行查询的优化之外还有那些呢?
前些天看了一个老外写的程序,在
mysql
查询中使用了很多
limit
关键字,这就让我很感兴趣了,因为在我印象中,
limit
关键字似乎更多被使用
mysql
数据库的程序员用来做查询分页(当然这也是一种很好的查询优化),那在这里举个例子,假设我们需要一个分页的查询
,oracle中一般来说都是用以下
sql
句子实现:
select * from
( select a1.*, rownum rownum_
from testtable a1
where rownum > 20)
where rownum_ <= 1000
这个语句就能查询到
testtable
表中的
20
到
1000
记录,而且还需要嵌套查询,效率不会太高,看看
mysql
的实现:
select * from testtable a1 limit 20,980;
这样就能返回
testtable
表中的
21
条到(
20
+
980
=)
1000
条的记录。
实现语法确实简单,但如果要说这里两个
sql
语句的效率,那就很难做比较了,因为在
mysql
中
limit
选项有多种不同的解释方式,不同方式下的速度差异是很大的,因此我们不能从这语句的简洁程度就说谁的效率高。
不过对程序员来说,够简单就好,因为维护成本低,呵呵。
下面讲讲这个
limit
的语法吧:
select ……. --select
语句的其他参数
[limit {[offset,] row_count | row_count offset offset}]
这里
offset
是偏移量(这个偏移量的起始地址是
0
,而不是
1
,这点很容易搞错的)顾名思义就是离开起始点的位置,而
row-count
也是很简单的,就是返回的记录的数量限制。
eg. select * from testtable a limit 10,20 where ….
这样就能使结果返回
10
行以后(包括
10
行自身)的符合
where
条件的
20
条记录。
那么如果没有约束条件就返回
10
到
29
行的记录。
那这跟避免全表扫描有什么关系呢?
下面是
mysql
手册对
limit
参数优化扫描的一些说明:
在一些情况中,当你使用
limit
选项而不是使用
having
时,
mysql
将以不同方式处理查询。
l
如果你用
limit
只选择其中一部分行,当
mysql
一般会做完整的表扫描时,但在某些情况下会使用索引(跟
ipart
有关)。
l
如果你将
limit n
与
order by
同时使用,在
mysql
找到了第一个符合条件的记录后,将结束排序而不是排序整个表。
l
当
limit n
和
distinct
同时使用时,
mysql
在找到一个记录后将停止查询。
l
某些情况下,
group by
能通过顺序读取键
(
或在键上做排序
)
来解决,并然后计算摘要直到键值改变。在这种情况下,
limit n
将不计算任何不必要的
group
。
l
当
mysql
完成发送第
n
行到客户端,它将放弃余下的查询。
l
而
limit 0
选项总是快速返回一个空记录。这对检查查询并且得到结果列的列类型是有用的。
l
临时表的大小使用
limit #
计算需要多少空间来解决查询。
这里还有一些自己写的例子,明天再写上来……