[难得技术] Mysql的索引测试与sql语句优化
星期二, 4月 26th, 2011建立测试数据表
CREATE TABLE `milliontest` ( `id` INT( 11 ) NOT NULL AUTO_INCREMENT , `name` CHAR( 100 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' , `content` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `time` INT( 11 ) NOT NULL DEFAULT '0', `lastmodify` DATETIME NOT NULL, PRIMARY KEY ( `id` ) ) ENGINE = Myisam
用上面的语句创建一个测试用的表。表中包含5个字段,自增主键ID,标题名字name,内容content以及创建时间time与最后编辑时间lastmodify,其中time字段用时间戳而编辑时间为年月日格式。由于目前表内没有任何数据,接下来当然是往表里灌数据,灌上100W(唬人用)。
我写了一个php脚本来完成这个任务。代码如下,各位大大不要耻笑:
set_time_limit(0); $conn = mysql_connect('localhost', 'root', ''); mysql_select_db('test'); $titles = array( '任天堂3DS发售,2000RMB兲朝币', '明猪昨天买了飞行俱乐部', '前天第一次玩街霸网战虐人了!' ); $contents = array( '据美国国家地理网站报道,美国“国家地理新闻”网站刊登了过去一周的精彩太空图片。 这些图片集中展现了极光、土卫一“米玛斯”、Abell 383星系团以及好似绿龙般的SH 2-235星云等壮观景象', '由于北极气候变暖,大量永冻土带融化,流入海洋。新研究发现,北极部分地区的永 久冻结带每年遭侵蚀的程度最多达到100英尺(约合30米)。'); $max = 1000000; mysql_query("set names utf8"); for($i = 0; $i < $max; $i++) { $tn = array_rand($titles); $cn = array_rand($contents); $time = time(); $lastmodify = date('Y-m-d H:i:s'); $res = mysql_query('insert into milliontest set name="'.$titles[$tn].'", content="'.$contents[$cn].'", time="'.$time.'", lastmodify="'.$lastmodify.'"'); file_put_contents('million_log.txt', $i); }
花了20多分钟时间数据库里终于有100w的数据了,泪流满面。那么下面就打开mysql终端开始华丽的测试一下。
select * from milliontest where time=1303812283; /*略去搜索结果*/ 146 rows in set (8.16 sec)
一条简单的查询就花了小小的8秒钟时间哦,要是100个人同时访问某个页面而同时运行了这条简单的语句,结果会怎么样咩?
这里我又做了另一个测试,注意跟上面那条sql语句的区别:
select * from milliontest where time='1303812283'; /*略去搜索结果*/ 146 rows in set (55.98 sec)
看到这查询时间,我自己都扭曲了,我只是查询一个想要的结果而已,却花56秒近1分钟的时间来等待查询。所以小提一下sql语句中各位注意一下引号吧。
又做了几组测试,时间多在8秒波动,有空各位自己慢慢测~
现在给time字段加一个索引
mysql> alter table milliontest add index (`time`); Query OK, 1000000 rows affected (33.88 sec) Records: 1000000 Duplicates: 0 Warnings: 0
建完索引,继续做一下上面的测试吧,嘻嘻。
mysql> select * from milliontest where time='1303812291'; 615 rows in set (0.05 sec)
加了索引后这次花了0.05秒,相对之前的数据,速度提升相当多吧哈哈哈。不过这么简单的查询却花了0.05秒,对于并发量大的时候估计也不乐观咩,咱们试试去掉引号?
mysql> select * from milliontest where time=1303812283; 146 rows in set (0.00 sec)
爽吧!花费时间0.00!
体会到了索引带来的好处了吧,不过话说我突然想起来,跑去看了一下这张表占的磁盘容量,泪流满面我没找到wamp这个软件吧索引文件丢到哪去了,总之之前我在自己ubuntu下做的测试好像加表数据占了磁盘800M还是多少,忘了
分页的SQL优化(limit优化)
之前在网上看的时候看到很多关于limit优化的文章,不小心看到一篇分页优化,哎哟看完那篇文章之后,我突然恍然大悟,附我跟主管的某段对话:
主管:好像现在后台有点慢?
我:估计是数据正在批量入库的缘故,不快。
但事后我重新测试了下后台,速度还是NN慢。刚好想到某篇分页测试的文章,提到:
select id,name from milliontest limit 0,20;的速度与select id,name from milliontest limit N,20;
不一样,查询结果的速度取决于N,也就是N越大,速度越慢。
嘴巴说没什么用,还是看事实。
mysql> select id,name from milliontest limit 0,20; 20 rows in set (0.00 sec) 而 mysql> select id,name from milliontest limit 100000,20; 20 rows in set (0.25 sec) 再看 mysql> select id,name from milliontest limit 500000,20; 20 rows in set (1.05 sec)
明显查询时间有了小增长吧。后面的时间更恐怖哟。所以很多论坛之类的,数据太久的就不显示出来了,或者加缓存,那是其他的技术咯。 (更多…)