mysql 索引- 笔记
索引
mysql最常用的索引结构是btree(O(log(n))),但是总有一些情况下我们为了更好的性能希望能使用别的类型的索引。hash就是其中一种选择,例如我们在通过用户名检索用户id的时候,他们总是一对一的关系,用到的操作符只是=而已,假如使用hash作为索引数据结构的话,时间复杂度可以降到O(1)。不幸的是,目前的mysql版本(5.6)中,hash只支持MEMORY和NDB两种引擎,而我们最常用的INNODB和MYISAM都不支持hash类型的索引。
1、BTree索引:
BTree(多路搜索树,并不是二叉的)是一种常见的数据结构。使用BTree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。按照翻译,B 通常认为是Balance的简称。这个数据结构一般用于数据库的索引,综合效率较高。
B-Tree索引可以被用在像=,>,>=,<,<=和BETWEEN这些比较操作符上。而且还可以用于LIKE操作符,只要它的查询条件是一个不以通配符开头的常量。
EXPLAIN select * from blog.my_user where `name` in ('rhythmk251','rhythmk2151','rhythmk7251','rhythmk685');
+----+-------------+---------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | my_user | ALL | NULL | NULL | NULL | NULL | 778424 | Using where |
+----+-------------+---------+------+---------------+------+---------+------+--------+-------------+
1 row in set
添加 idx_name 索引:
ALTER TABLE blog.`my_user`
ADD INDEX `idx_name` (`name`) USING BTREE ; mysql> EXPLAIN select * from blog.my_user where `name` in ('rhythmk251','rhythmk2151','rhythmk7251','rhythmk685');
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+
| 1 | SIMPLE | my_user | range | idx_name | idx_name | 303 | NULL | 4 | Using where |
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+ mysql> EXPLAIN select * from blog.my_user where `name` LIKE 'rhythmk830%';
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+
| 1 | SIMPLE | my_user | range | idx_name | idx_name | 303 | NULL | 11 | Using where |
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+
1 row in set
任何一个没有覆盖所有WHERE中AND级别条件的索引是不会被使用的。也就是说,要使用一个索引,这个索引中的第一列需要在每个AND组中出现。
mysql> EXPLAIN select * from blog.my_user where `name` LIKE 'rhythmk830%' or age>35;
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | my_user | ALL | idx_name | NULL | NULL | NULL | 7266 | Using where |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
1 row in set
mysql> EXPLAIN select * from blog.my_user where `name` LIKE 'rhythmk830%' and age>35;
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+
| 1 | SIMPLE | my_user | range | idx_name | idx_name | 303 | NULL | 11 | Using where |
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+
1 row in set
有时候mysql不会使用索引,即使这个在可用的情况下。例如当mysql预估使用索引会读取大部分的行数据时。(在这种情况下,一次全表扫描可能比使用索引更快,因为它需要更少的检索)。然而,假如语句中使用LIMIT来限定返回的行数,mysql则会使用索引。因为当结果行数较少的情况下使用索引的效率会更高。
mysql> EXPLAIN select * from blog.my_user where `name` <> 'rhythmk830' ;
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | my_user | ALL | idx_name | NULL | NULL | NULL | 7769 | Using where |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
1 row in set mysql> EXPLAIN select * from blog.my_user where `name` <> 'rhythmk830' limit 5;
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+
| 1 | SIMPLE | my_user | range | idx_name | idx_name | 303 | NULL | 5658 | Using where |
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+
1 row in set
2、Hash 索引特征:
Hash类型的索引有一些区别于以上所述的特征:
精确查找非常快(包括= <> 和in),其检索效率非常高,索引的检索可以一次定位,不像BTree 索引需要从根节点到枝节点,所以 Hash 索引的查询效率要远高于 B-Tree 索引。
不适合:
1、不适合模糊查询和范围查询(包括like,>,<,between……and等)。由于 Hash 索引比较的是进行 Hash 运算之后的 Hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的 Hash 算法处理之后的 Hash 值的大小关系,并不能保证和Hash运算前完全一样;
2、不适合排序,数据库无法利用索引的数据来提升排序性能,同样是因为Hash值的大小不确定;
3、复合索引不能利用部分索引字段查询,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。
3、备注:
1、索引列需要根据业务判断 ,在where条件中出现的列。
2、使用索引需要考虑某列中值的分布,比如性别,搜索 “男/女” 都会得出大约一半的行,所有索引没有多大的用处。
3、使用短索引好处多多。对字符串进行索引的时候,应该指定一个前缀长度。索引长度小,节约索引空间及磁盘IO同时让索引,短的值比较起来更快,同时Mysql 可以在内存中存储更多的值。
4、利用最左前缀。创建一个多列索引,可起几个索引的作用。因为可利用索引最左边的列来匹配行。这样的列集称为最左前缀。
5、不要过度索引。 额外的索引需要占用空间,并降低写操作的性能。修改表的时候索引必须进行更新,有时可能需要重构,索引越多时间越长。索引太多,也可能导致MYSQL选择不到最优索引。
6、INNODB 存储引擎,记录优先按主键保存,如果没有主键,但是有唯一索引那么就按唯一索引列保存。如果两者都没有,那么表中会生成一个内部列。按照这个列的顺序保存,InnoDB普通索引都会保存主键,所以主键要尽可能选择较短的数据类型。
7、尽量避免NULL:应该指定列为NOT NULL,除非你想存储NULL。在MySQL中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值。
8、使用--查看当前session所有已产生的profile
mysql> show profiles;
mysql 索引- 笔记的更多相关文章
- MySql索引笔记
MySQL 索引是什么 MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和 ...
- mysql 索引笔记
MyISAM引擎的B+Tree的索引 通过上图可以直接的看出, 在MyISAM对B+树的运用中明显的特点如下: 所有的非叶子节点中存储的全部是索引信息 在叶子节点中存储的 value值其实是 数据库中 ...
- mysql 索引 笔记1
#不同的存储引擎支持的索引类型也不一样 InnoDB 支持事务,支持行级别锁定,支持 B-tree.Full-text 等索引,不支持 Hash 索引: MyISAM 不支持事务,支持表级别锁定,支持 ...
- 关于Mysql索引的笔记
MySQL索引原理 索引目的 索引的目的在于提高查询效率,可以类比字典,如果要查“mysql”这个单词,我们肯定需要定位到m字母,然后从下往下找到y字母,再找到剩下的sql.如果没有索引,那么你可能需 ...
- mysql学习笔记-- 多表查询之外键、表连接、子查询、索引
本章主要内容: 一.外键 二.表连接 三.子查询 四.索引 一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复 ...
- SQL学习笔记五之MySQL索引原理与慢查询优化
阅读目录 一 介绍 二 索引的原理 三 索引的数据结构 四 聚集索引与辅助索引 五 MySQL索引管理 六 测试索引 七 正确使用索引 八 联合索引与覆盖索引 九 查询优化神器-explain 十 慢 ...
- SQL学习笔记之MySQL索引知识点
0x00 概述 之前写过一篇Mysql B+树学习,简单的介绍了B+数以及MySql使用B+树的原因, 有了这些基础知识点,对MySql索引的类型以及索引使用的一些技巧,就比较容易理解了. 0x01 ...
- Mysql 索引复习笔记
之前学习索引后由于一直没怎么用,所以也只是粗略看了一下,最近发现索引的用处很大,并且也很多知识点,在此做复习记录. 什么是索引? 百度百科是这样描述的: 索引是为来加速对表中数据行中的检索而创建的一种 ...
- Mysql索引学习笔记
1.btree索引与hash索引 下列范围查询适用于 btree索引和hash索引: SELECT * FROM t1 WHERE key_col = 1 OR key_col IN (15,18,2 ...
随机推荐
- Qt 二级菜单栏 中文无法输入问题
问题描述:Qt5.3.1版本在建立主界面的二级菜单的时候,中文无法输入,而英文确是可以输入的.(首先我在网页上面搜索了一下,他们说是Qt的设计问题.) 解决方法: (1)粘贴复制,把中文写在其他的地方 ...
- PHP动态压缩js,css
PHP动态压缩js,css 列表项 标签: PHP 正式发布产品时,我们希望将项目里的js,css合并压缩,以减少http请求.防止轻易查看源代码. 使用 只需要在头部引入一下代码即可: <me ...
- Atitit. 异常的使用总结最佳实践java .net php Vo8f
Atitit.java 异常的使用总结最佳实践 Vo8f 1. 为什么使用异常 1 2. 用throw抛出一个异常到catch子句中与通过函数调用传递一个参数两者基本相同. 2 3. S E H的主要 ...
- new一个Object对象占用多少内存?
Java的自动内存管理机制省却了很多编码工作,大大地提高了Java的生产力,而且JVM的性能也越来越好,特别是G1的出现,改善了垃圾回收中stop the world的状况. 也许很多人都没有考虑过这 ...
- 使用Maven编译项目遇到——“maven编码gbk的不可映射字符”解决办法 ——转载
一.问题描述 今天在MyEclipse中使用Maven编译项目源代码时,结果如下了如下的错误
- apache url rewrite 的RewriteRule参数详解
apache url rewrite 的RewriteRule参数详解 我们经常会在apache那边对一些url进行一些重写操作,那么就会涉及到很多的重写策略的选择,比如重定向的方式,参数的处理,规则 ...
- Windows Server 2012 如何实现多个用户远程桌面登陆?
Windows Server 2012 如何实现多个用户远程桌面登陆?说明:Windows Server 2012默认情况下,只运行2个用户远程桌面登陆,这里我们可以通过安装远程桌面会话主机配置来实现 ...
- SQLite 批量insert - 如何加速SQLite的插入操作
本人翻译, 原文见: http://tech.vg.no/2011/04/04/speeding-up-sqlite-insert-operations/ 我正在开发一个Android程序, 它使用S ...
- Android项目实战--手机卫士开发系列教程
<ignore_js_op> banner131010.jpg (71.4 KB, 下载次数: 0) 下载附件 保存到相册 2 分钟前 上传 Android项目实战--手机卫士01- ...
- StringBuffer&StringBuilder区别详解
序言 StringBuffer与StringBuilder是java.lang包下被大家熟知的两个类.其异同为:一.长度都是可扩充的:二.StringBuffer是线程安全的,StringBuilde ...