对于大数据量的表格,尤其是百万行以上的数据表,一定要对其建立索引,否则查询速度极慢。(参考后面的测试结果)
建立索引时需注意:
MySQL的索引有两种:单列索引(即在某一列上建索引)、多列组合索引(即在多个列上建立同一个索引),不像SQL Server分聚集索引,非聚集索引。
如何建立单列索引:
格式:CREATE INDEX 索引名 on 表名(列名) 例如:
CREATE INDEX idx_geoinfo_tiny_cabid ON geoinfo_tiny (cabid)#创建一个名为idx_geoinfo_tiny_cabid的索引,该索引建立在geoinfo_tiny表上的cabid列上面
如何建立多列组合索引:
格式:CREATE INDEX 索引名 on 表名(列名1,列名2,列名3,...) 例如: #创建一个名为idx_geoinfo_tiny_objectid_occupancy_time_cabid的索引,该索引建立在geoinfo_tiny表上的objectid,occupancy,occur_time,cabid等四个列上面
CREATE INDEX idx_geoinfo_tiny_objectid_occupancy_time_cabid ON geoinfo_tiny (objectid,occupancy,occur_time,cabid)
应该在哪个列上建立索引?建组合索引还是单列索引?
先说第一问,应该在哪个列上建立索引?
答:得根据自己的查询需求来,哪一列需要经常查询就在哪一列上建索引,一般是sql语句中where子句中的列,例如对于sql语句
SELECT objectid,occur_time,latitude,longitude,cabid from geoinfo_tiny where cabid='afmorc' and time(occur_time)>time('07:00:00') and time(occur_time)<time('12:00:00')
ORDER BY occur_time ASC
where子句中作为判断依据的cabid列和time列,这两个列上应该建立索引。
至于该建立组合索引还是单列索引,如不能确定,可以都试试,看哪个效果好。
我本机上有一个表,名为geoinfo_tiny,6个字段,从.txt文件导入了2,867,457行数据(如何使用Python快速、大批量地导入数据,请看http://www.cnblogs.com/aaronhoo/p/5152292.html)
创建表:
CREATE TABLE `geoinfo_tiny` (
`objectid` int(11) NOT NULL AUTO_INCREMENT ,
`latitude` double NOT NULL ,
`longitude` double NOT NULL ,
`occupancy` bit(1) NOT NULL ,
`occur_time` datetime NOT NULL ,
`cabid` varchar(16)
待测试的查询语句:
SELECT objectid,occur_time,latitude,longitude,cabid from geoinfo_tiny where cabid='afmorc' and time(occur_time)>time('07:00:00') and time(occur_time)<time('12:00:00')
ORDER BY occur_time ASC
测试1:不建立任何索引,直接查询
结果:
[SQL] SELECT objectid,occur_time,cabid from geoinfo_tiny where cabid='eckecky' and time(occur_time)>time('07:00:00') and time(occur_time)<time('12:00:00')
ORDER BY occur_time ASC 受影响的行: 0 时间: 4.254s
测试2:只在cabid列上建立索引
CREATE INDEX idx_geoinfo_tiny_cabid ON geoinfo_tiny (cabid)
结果:
[SQL] SELECT objectid,occur_time,cabid from geoinfo_tiny where cabid='amwibs' and time(occur_time)>time('07:00:00') and time(occur_time)<time('12:00:00')
ORDER BY occur_time ASC
受影响的行: 0 时间: 0.147s
测试3:只在occur_time列上建立索引
CREATE INDEX idx_geoinfo_tiny_time ON geoinfo_tiny (occur_time)
结果:
[SQL] SELECT objectid,occur_time,cabid from geoinfo_tiny where cabid='ancorjo' and time(occur_time)>time('07:00:00') and time(occur_time)<time('12:00:00')
ORDER BY occur_time ASC 受影响的行: 0
时间: .668s
测试4:在cabid、occur_time列上分别建立单列索引(此时该表上有2个单列索引)
结果:
[SQL] SELECT objectid,occur_time,cabid from geoinfo_tiny where cabid='atfrim' and time(occur_time)>time('07:00:00') and time(occur_time)<time('12:00:00')
ORDER BY occur_time ASC 受影响的行: 0
时间: 0.195s
测试5:在cabid、occur_time列上建立组合索引(此时该表上只有一个组合索引,没有单列索引)
结果:最少0.038s,最多0.305s
测试6:在cabid,occur_time,objectid,occupancy四个列上建立组合索引
结果:4.249s-4.703s
测试结果分析:
对比测试1、测试2可知,建立索引之后查询速度大大提升。
对比测试2、测试3可知,建立单列索引时,最好选择在int、float型等基本类型的列上建索引,若在复杂数据类型如datetime等列上,效果较差,和没建一样。
对比测试2、测试4可知,增加单列索引并不一定能提高查询速度。
对比测试2、4、5可知,组合索引比分别建两个单列索引似乎更有效。
对比测试1、2、4、6可知,建组合索引时,并不是列越多越好,若与where子句无关的列参与进来会使得索引失去效果,甚至更糟。
更多注意事项,请参考http://itindex.net/detail/54651-mysql-%E5%AD%A6%E4%B9%A0-%E7%B4%A2%E5%BC%95