面试题二:索引问题
索引是一种允许直接访问数据表中某一数据行的树型结构,为了提高查询效率而引入,是独立于表的对象,可以存放在与表不同的表空间(TABLESPACE)中。索引记录中存有索引关键字和指向表中数据的指针(地址)。对索引进行的I/O操作比对表进行操作要少很多。
索引一旦被建立就将被Oracle系统自动维护,查询语句中不用指定使用哪个索引,是一种提高查询效率的机制。
- CREATE INDEX idx_emp_ename ON emp(ename);新建
- CREATE INDEX idx_emp_job_sal ON emp(job, sal);新建
- CREATE INDEX emp_ename_upper_idx ON emp(UPPER(ename));新建
- ALTER INDEX idx_emp_ename REBUILD;//重建索引
- DROP INDEX idx_emp_ename;删除
- 为经常出现在WHERE子句中的列创建索引
- 为经常出现在ORDER BY、DISTINCT后面的字段建立索引。如果建立的是复合索引,索引的字段顺序要和这些关键字后面的字段顺序一致
- 为经常作为表的连接条件的列上创建索引
- 不要在经常做DML操作的表上建立索引
- 不要在小表上建立索引
- 限制表上的索引数目,索引并不是越多越好
- 删除很少被使用的、不合理的索引
一、索引优缺点
MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。
索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。
创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。
实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。
上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。
建立索引会占用磁盘空间的索引文件。
二、索引类型
Mysql目前主要有以下几种索引类型:FULLTEXT,HASH,BTREE,RTREE。
1. FULLTEXT
即为全文索引,目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。
全文索引并不是和MyISAM一起诞生的,它的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题。
2. HASH
由于HASH的唯一(几乎100%的唯一)及类似键值对的形式,很适合作为索引。
HASH索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。但是,这种高效是有条件的,即只在“=”和“in”条件下高效,对于范围查询、排序及组合索引仍然效率不高。
3. BTREE
BTREE索引就是一种将索引值按一定的算法,存入一个树形的数据结构中(二叉树),每次查询都是从树的入口root开始,依次遍历node,获取leaf。这是MySQL里默认和最常用的索引类型。
4. RTREE
RTREE在MySQL很少使用,仅支持geometry数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。
相对于BTREE,RTREE的优势在于范围查找。
ps. 此段详细内容见此片博文:Mysql几种索引类型的区别及适用情况
三、索引种类
普通索引:仅加速查询
唯一索引:加速查询 + 列值唯一(可以有null)
主键索引:加速查询 + 列值唯一(不可以有null)+ 表中只有一个
组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并
全文索引:对文本的内容进行分词,进行搜索
索引合并,使用多个单列索引组合搜索
覆盖索引,select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖
2.索引是否越多越好?(面试问答)
大多数情况下索引能大幅度提高查询效率,但是:
数据的变更(增删改)都需要维护索引,因此越多意味着维护成本越高;
更多的索引意味着需要更多的空间(一本书半本目录?);
过小的表,建索引可能会更慢;
3. 什么情况下应不建或少建索引
表记录太少
如果一个表只有5条记录,采用索引去访问记录的话,那首先需访问索引表,再通过索引表访问数据表,一般索引表与数据表不在同一个数据块,这种情况下ORACLE至少要往返读取数据块两次。而不用索引的情况下ORACLE会将所有的数据一次读出,处理速度显然会比用索引快。
如表zl_sybm(使用部门)一般只有几条记录,除了主关键字外对任何一个字段建索引都不会产生性能优化,实际上如果对这个表进行了统计分析后ORACLE也不会用你建的索引,而是自动执行全表访问。如:select * from zl_sybm where sydw_bh=’5401’(对sydw_bh建立索引不会产生性能优化)
经常插入、删除、修改的表
对一些经常处理的业务表应在查询允许的情况下尽量减少索引,如zl_yhbm,gc_dfss,gc_dfys,gc_fpdy等业务表。
数据重复且分布平均的表字段
假如一个表有10万行记录,有一个字段A只有T和F两种值,且每个值的分布概率大约为50%,那么对这种表A字段建索引一般不会提高数据库的查询速度。
经常和主字段一块查询但主字段索引值比较多的表字段
如gc_dfss(电费实收)表经常按收费序号、户标识编号、抄表日期、电费发生年月、操作 标志来具体查询某一笔收款的情况,如果将所有的字段都建在一个索引里那将会增加数据的修改、插入、删除时间,从实际上分析一笔收款如果按收费序号索引就已 经将记录减少到只有几条,如果再按后面的几个字段索引查询将对性能不产生太大的影响。
以上,简而言之,就是:
一般来说,列的值唯一性太小(如性别,类型什么的),不适合建索引;
太长的列,可以选择只建立部分索引,(如:只取前十位做索引);
更新非常频繁的数据不适宜建索引
4.哪些情况不能用索引
like “%xxx”
not in , !=
对列进行函数运算的情况(如 where md5(password) = “xxxx”)
WHERE index=1 OR A=10
5.如何查看, 分析索引信息?
show index from tablename;
explain select ……;
explain在phoenix中亦可同样使用
- Java面试题——索引解决什么问题?遵循怎样的原则?
- 关于mysql索引失效问题
- mongo 索引问题
- 解决AndroidStudio添加ProjectLibary后在编译时遇到的各种问题之解决方式索引(finished with non-zero exit va
- 经典面试题——n皇后问题
- 【我解C语言面试题系列】006 按位反转整数问题
- lucene 索引合并问题
- [各种面试题] 整数划分问题
- 主键约束自动建立索引问题及约束状态分析
- Asp.net Mvc问题索引
- 面试题之10亿正整数问题--完整解答
- 链表面试题之约瑟夫环问题
- 数组在for循环中使用splice方法导致索引错乱的问题
- 摔棋子(摔杯子)问题——解答Google的一道面试题
- 有关阿里巴巴技术部面试题智力问题部分
- 2014.06.26 MySQL 用索引解决的一个性能问题
- 索引相关问题讨论
- 秒级索引中录像长度偏少的问题
- 15个顶级Java多线程面试题及回答 / Java程序员面试中的多线程问题
- 面试题之进程间通信问题