数据库有没有建过索引?
没有。
居然没有建过索引,查询难道不用索引么!!!
数据库的数据库索引对程序员来说是透明的,意味着数据库建立索引之前和之后,你的SQL语句都可以正常运行,索引的运用只是数据库引擎工作时候的优化手段。但是,这不是意味着数据库索引仅仅是数据库设计和运维者的事情,对于一个程序员如果对数据库已有的索引有所了解,还是可以大大优化程序员数据库的查询和修改语句执行效率的,以免你的低效查询语句称为拖累整个系统性能的Black Sheep。本文对MySQL数据类型和索引建立、优化进行整理,现在数据库引擎默认都是InnoDB的,而且目前MySQL/MariaDB应用于生产环境时候,应该都是用的这个引擎吧。
数字类型算是最简单的了,主要差异在于各个类型的取值范围大小限制,和对存储空间字节数的需求。数字类型当然是在满足情况的条件下越短越好,一方面MySQL每行有65535字节长度的限制,同时更宽的数据类型意味着对CPU、内存、磁盘I/O带来压力。
类型 | 长度 |
---|---|
TINYINT | 1 |
SMALLINT | 2 |
MEDIUMINT | 3 |
INTEGER | 4 |
BIGINT | 5 |
在数据库设计的时候,常常看到这些整形有个前缀长度,其实这对其类型本身的存储长度和精度没有影响,只会关系到某些交互式工具显示出来的字符个数。
类型 | 长度 |
---|---|
FLOAT | 4 |
FLOAT(p) [0,24] | 4 |
FLOAT(p) [25,53] | 8 |
DOUBLE,REAL | 8 |
计算机的浮点运算都是不精确的,如果要实现精确浮点运算,就需要使用DECIMAL类型。
DATE:’1000-01-01’ to ‘9999-12-31’
DATETIME:’1000-01-01 00:00:00’ to ‘9999-12-31 23:59:59’
TIMESTAMP:’1970-01-01 00:00:01’ UTC to ‘2038-01-19 03:14:07’ UTC
TIMESTAMP存储的范围比DATETIME要小,但是空间利用率也最高。MySQL支持的时间精度最高为1s,如果更精确的存储,就必须自己定义存储格式了。
MySQL中的字符串类型比较多也比较的复杂,各个字符串类型的差别不仅仅在存储时候的空间占用,对存取时候字段某位的strip和padding还有差异。对于类型CHAR/VARCHAR/TEXT是跟本地字符集相关的,这会影响到实际占用空间的字节数、字符比较等。
类型 | 长度 |
---|---|
CHAR(M) | Mxw bytes |
BINARY(M) | M bytes |
VARCHAR(M), VARBINARY(M) | L+1/L+2 bytes |
TINYBLOB, TINYTEXT | L+1 bytes |
LOB, TEXT | L+2 bytes |
MEDIUMBLOB, MEDIUMTEXT | L+3 bytes |
LONGBLOB, LONGTEXT | L+4 bytes |
根据官方手册,CHAR/BINARY及其衍生的类型的数据是存储在表的行内部(inline)的,而对于BLOB和TEXT类型,每一个字段只占用该行9-12(1~4+8)个字节(用于数据的地址和长度),实际的数据是存储在Row Buffer之外位置的。所以对于经常访问的字符串类型,而长度又不是特别的大,还是建议用VARCHAR(M)的数据类型,性能会比TEXT快不少。
数据库索引可以用来快速找到需要的行,否则的话MySQL就需要一行一行的遍历,查询效率自然相当的低。
MySQL支持的索引包括PRIMARY KEY、UNIQUE、INDEX、FULLTEXT类型的索引。前面说过,FULLTEXT类型的全文索引在中文下基本是报废的,在此就不予讨论了。
特别注意的是,对于索引列只能使用单纯的列名,而不能是表达式或者函数的一部分,比如age+2、TO_DAYS(date_col),引擎在检索的时候才能使用索引。
(1) 对于字符串类型,可以指定索引前缀长度(且对于BLOB/TEXT前缀长度参数是必须的),在InnoDB表中其前缀长度最长是767 bytes,且参数M是用bytes计量的。所以太长的字符串,建立BTree索引浪费比较大,这时候用手动模拟HASH索引是个方法,不过这种方式对字符串无法灵活的使用前缀方式查询(例如LIKE这类的操作)。
(2) 在建立多列索引的时候,必须按照从左到右的顺序使用全部或部分的索引列,才能充分的使用组合索引,比如:(col1, col2, col3)使用(col1)、(col1, col2)、(col1, col2, col3)有效。在查询语句中会一直向右匹配直到遇到范围查询(>,<,BETWEEN,LIKE)就停止匹配,其后的索引列将不会使用索引来优化查找了。
(3) 索引不是建立的越多、越长越好,因为索引除了占用空间之外,对后续数据库的增加、删除、修改都有额外的操作来更新索引,所以对索引列和字符串前缀长度,都参考选择性(Selectivity)这个指标来确定:选择性定义为不重复的索引值和数据总记录条数的比值,其选择性越高,那么索引的查询效率也越高,对于性别这种参数,建立索引根本没有意义。
本文完!
参考文献: