本博客文章已转移到独立博客,请点击做最好的三三查看全文。
10
21
2012
4

SQLite中获取随机记录的两种方法以及效率比较

本博客文章已转移到独立博客,查看本文请点击做最好的三三查看全文。

SQLite这个数据库我自己也用的很多。比起mysql它的好处在于不用设置繁琐的host啊username,password,database什么的,直接一个文件上去就好了,类似于Access的方式哈(Access和SQLite能比么~!)。

之前也研究过MySQL上的随机数据获取方法,Google一下一大堆,我就不多说了。总之看了很多MySQL上的文章,SQLite的却没有多少,于是我就自己研究了一下。

我用的环境是Apache/2.2.16 (Win32) PHP/5.2.14,加上PDO的SQLite3接口。还用到一个类库是我自己写的LFPSQlite库,这个库我没有发布过,因为实在是写的太坑了,不想丢丑什么的。

言归正传。今天说的两种获取随机记录的方法,第一种是这样的:

SELECT COUNT(*) FROM 'test';
SELECT * FROM 'test' LIMIT 1 OFFSET #;

其中#是rand(0,$count-1)。

第二种是这样的

SELECT * FROM 'test' ORDER BY random() LIMIT 1;

两种方法的效率究竟如何呢?先来理论分析下。

首先第一种方法是查出数据行数,然后用偏移值来实现读取数据。这两条SQL命令应当是非常快的。第二种方法是用random()排序。虽然有LIMIT 1来限定,但是SQLite应该会将整个表排一次序,那么这个方法就应当比上面慢很多。

具体如何呢?我们来分析一下。我写了一个小脚本,因为用到了我那个没公开的库,所以脚本也就不公开了。我很无聊的把它传到了一个免费空间上,访问地址是:http://jiaowo33.cwsurf.de/sqlite/test.php?times=5 最后那个5可以改成1~200的任意值。用的数据库比较小,只有2W多行。如果你感兴趣可以下载过来看看?在/sqlite/demo.db(406KB)这个位置。

分别执行1,10,100,200次,然后我们来看看程序运行的结果:

信息: 数据库记录数:20915.
信息: 执行1次 COUNT(*)+OFFSET所需时间为0.000886917114258s.
信息: 执行1次OREDER BY RANDOM所需时间为0.0190088748932s.
信息: 效率差值:0.0181219577789s
信息: 执行10次 COUNT(*)+OFFSET所需时间为0.00564503669739s.
信息: 执行10次OREDER BY RANDOM所需时间为0.193027973175s.
信息: 效率差值:0.187382936478s
信息: 执行100次 COUNT(*)+OFFSET所需时间为0.0537490844727s.
信息: 执行100次OREDER BY RANDOM所需时间为1.947660923s.
信息: 效率差值:1.89391183853s
信息: 执行200次 COUNT(*)+OFFSET所需时间为0.105569839478s.
信息: 执行200次OREDER BY RANDOM所需时间为4.20832800865s.
信息: 效率差值:4.10275816917s

效果显而易见。count(*)的执行效率明显比order by random()要高得多。

本博客内容除标明外均为原创;转载请保留原文地址或pingback;所有代码所有权归作者所有;在此公布的所有作者标明为本人的代码均可非商业自由使用。
本博客文章已转移到独立博客,发表评论请点击做最好的三三查看全文。
Category: PHP | Tags: php sqlite 随机记录 | Read Count: 2253
wxg4net 说:
Nov 02, 2012 10:14:58 AM

COUNT(*) 不加查询条件的话 可直接获取总数据条数,这个变量在mysql,sqlite中是由数据库更新的

Avatar_small
三三 说:
Nov 06, 2012 08:18:43 PM

说的没错,所以效率要高很多,而不像是order by random每次请求都要重新排一次序。

leon 说:
Mar 06, 2013 01:01:16 PM

不清楚第一种方法怎样用,这样子吗?
SELECT COUNT(*) FROM 'test';
SELECT * FROM 'test' LIMIT 1 OFFSET rand(0,$count-1);

运行结果是Count(*)的值,请求帮助

Avatar_small
三三 说:
Mar 06, 2013 03:29:04 PM

不,他们其实不是纯粹的SQL语句。
你应该需要先使用SELECT COUNT(*) FROM 'test'; 从test表中得到总数,存储到你程序中的变量$count里;然后再使用SELECT * FROM 'test' LIMIT 1 OFFSET rand(0,$count-1);来查询一个随机的条目。
需要注意的是这里的第二条是SQLite的SQL语句,MySQL可能会不一样。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com

Power by Chito 1.3.1 beta

| Theme: Aeros 2.0 by TheBuckmaker.com