mysql索引

mysql——索引

╄→尐↘猪︶ㄣ 提交于 2020-01-23 21:05:06
1. 索引的常见模型 索引可以用于提高读写效率的数据结构很多, 这里介绍三种常见、 也比较简单的数据结构, 它们分别是哈希表、 有序数组和搜索树 1. 哈希表 哈希的思路很简单, 把值放在数组里, 用一个哈希函数把key换算成一个确定的位置, 然后把value放在数组的这个位置。 不可避免地, 多个key值经过哈希函数的换算, 会出现同一个值的情况。 处理这种情况的一种方 法是, 拉出一个链表 。 缺点就是 : 哈希表这种结构适用于只有等值查询的场景, 因为不是有序的, 所以哈希索引做区间查询的速度是很慢的。 2. 有序数组 有序数组在等值查询和范围查询场景中的性能就都非常优秀 , 如果仅仅看查询效率, 有序数组就是最好的数据结构了。 但是, 在需要更新数据的时候就麻烦了, 你往中间插入一个记录就必须得挪动后面所有的记录, 成本太高 缺点 :中间插入一个记录就必须得挪动后面所有的记录, 成本太高 有序数组索引只适用于静态存储引擎, 比如你要保存的是2017年某个城市的所有人口信息, 这类不会再修改的数据 3.搜索树 N叉树由于在读写上的性能优点, 以及适配磁盘的访问模式, 已经被广泛应用在数据库引擎中了 2. InnoDB 的索引模型 在InnoDB中, 表都是根据主键顺序以索引的形式存放的, 这种存储方式的表称为索引组织表。 InnoDB使用了B+树索引模型,

MySQL 优化 —— IS NULL 优化

北城以北 提交于 2020-01-23 18:10:42
引言 本博客翻译自 MySQL 官网: IS NULL Optimization , MySQL版本 5.7。 MySQL 对 IS NULL 的优化 MySQL 可以对 IS NULL 执行和常量等值判断(列名 = 常量表达式,如name = 'Tom')相同的优化。MySQL 可以利用索引和范围来搜索空值。 例如: SELECT * FROM tbl_name WHERE key_col IS NULL; SELECT * FROM tbl_name WHERE key_col <=> NULL; SELECT * FROM tbl_name WHERE key_col=const1 OR key_col=const2 OR key_col IS NULL; 如果 WHERE 子句包含一个 IS NULL 条件,而这个列却被声明为 NOT NULL,那么IS NULL表达式就会被优化掉。当列值未声明为非空,那么就不会发生这种优化(例如, LEFT JOIN 右侧的表)。 MySQL 也会 优化这样的条件组合 : col_name = expr OR col_name IS NULL ,这是在已解析的子查询中较常见的形式。如果发生了这种优化,那么 EXPLAIN 执行计划会出现 ref_or_null 。 This optimization can handle one IS

MySQL索引失效

让人想犯罪 __ 提交于 2020-01-23 07:53:13
OR:   查询条件包含or时,可能会导致索引失效   只有当or左右查询字段均为索引时,才会生效 组合索引:   组合索引,不是使用第一列索引,索引失效   下面是一些例子,假设索引是(col1, col2, col3),那么:   ...where col1 = 1 order by col2, col3;(√)   ...where col1 = 1 order by col2;(√)   ...where col1 > 1 order by col1, col2;(√)   ...where col1 > 1 order by col2, col3;(X) // Order By必须出现索引中的第1个字段   ...where col1 = 1 order by col2 desc, col3 asc;(X) //Order By中三个字段的排序方向必须相同,否则会导致索引失效   ...where col1 = 1 order by col2, col4;(X)   ...where col1 = 1 order by col3;(X)   ...where col1 = 1 and col2 in(1,3) order by col3;(X) 不能继续使用索引中范围条件(bettween、<、>、in等)右边的列 like 以%开头:   使用like模糊查询,当

MySql之索引底层深入解析

你。 提交于 2020-01-22 04:21:14
文章目录 1.索引概念 2.索引类型与创建 2.1.普通索引(Normal)又称 非唯一索引(None-Unique) 2.2.唯一索引(Unique) 2.3.全文索引(Fulltext) 3.索引数据结构存储模型推演 3.1.二分查找 3.2.二叉查找树(BST Binary Search Tree) 在线模拟 二叉查找树 3.3. 平衡二叉树(AVL Tree)(左旋、右旋) 1.索引概念 1. 数据库索引,是数据库的一个排序的数据结构,以协助快速查询、 更新数据库表中数据。 1. 首先数据是以文件的形式存放在磁盘上面的,每一行数据都有它的磁盘地址。如果没有索引的话, 要从 500 万行数据里面检索一条数据,只能依次遍历这张表的全部数据, 直到找到这条数据。 2. 但是有了索引之后,只需要在索引里面去检索这条数据就行了,因为它是一种特殊的专门用来快速检索的数据结构, 我们找到数据存放的磁盘地址以后,就可以拿到数据 了。就像我们从一本 500 页的书里面去找特定的一小节的内容, 肯定不可能从第一页开 始翻。那么这本书有专门的目录,它可能只有几页的内容,它是按页码来组织的, 可以根据拼音或者偏旁部首来查找,只要确定内容对应的页码,就能很快地找到我们想要的内容。 2.索引类型与创建 2.1.普通索引(Normal)又称 非唯一索引(None-Unique) 1. 普通索引

MySQL 优化---索引实战(三)

时光毁灭记忆、已成空白 提交于 2020-01-21 05:44:40
MySQL索引B+Tree优化实战 环境说明 Centos版本: CentOS Linux release 7.7.1908 (Core) Linux连接工具:SecureCRT MySQL Version: 5.7.28 MySQL连接工具:Navicate 知识扩展 Mysql中的UTF8是0-3个字节,Java中的UTF8是0-4个字节 ,在MySQL中设置字符集UTF8mb4才是0-4个字节 在MySQL4.0版本一下varchar代表的是字节 在MySQL4.0版本之后varchar代表的是字符 思考: char(10)能存储多少个中文?多少个英文? varchar(10)能存储多少个中文?多少个英文? 参考文档:https://dev.mysql.com/doc/refman/5.7/en/char.html 索引概念 索引是什么? 索引是帮助MySQL高效获取数据的数据结构! 官方解释:索引用于快速查找具有特定列值的行。没有索引,MySQL必须从第一行 开始,然后通 读整个表以找到相关的行。表越大,花费时间越长。如果表中有相关 列的索 引 MySQL可以快速确定要在数据文件中间查找的位置,而不必查看所有 数据。这比顺序读取每一行要快得多。 索引能干什么? 高数据查询的效率。 索引会影响where后面 的查找和order by 后面的排序。 索引的种类

MySQL两种存储引擎: MyISAM和InnoDB 简单总结

我是研究僧i 提交于 2020-01-21 00:16:47
MyISAM是MySQL的默认数据库引擎(5.5版之前),由早期的ISAM(Indexed Sequential Access Method:有索引的顺序访问方法)所改良。虽然性能极佳,但却 有一个缺点:不支持事务处理(transaction) 。不过,在这几年的发展下,MySQL也导入了InnoDB(另一种数据库引擎),以强化参考完整性与并发违规处理机制,后来就逐渐取代MyISAM。 InnoDB,是MySQL的数据库引擎之一,为MySQL AB发布binary的标准之一。InnoDB由Innobase Oy公司所开发,2006年五月时由甲骨文公司并购。与传统的ISAM与MyISAM相比,InnoDB的最大特色就是支持了ACID兼容的事务(Transaction)功能,类似于PostgreSQL。目前InnoDB采用双轨制授权,一是GPL授权,另一是专有软件授权。 MyISAM和InnoDB两者之间有着明显区别,简单梳理如下: 1) 事务支持 MyISAM不支持事务,而InnoDB支持。InnoDB的AUTOCOMMIT默认是打开的,即每条SQL语句会默认被封装成一个事务,自动提交,这样会影响速度,所以最好是把多条SQL语句显示放在begin和commit之间,组成一个事务去提交。 MyISAM是非事务安全型的,而InnoDB是事务安全型的,默认开启自动提交,宜合并事务,一同提交

MySQL SQL优化之字符串索引隐式转换

社会主义新天地 提交于 2020-01-20 22:17:40
之前有用户很不解:SQL语句非常简单,就是select * from test_1 where user_id=1 这种类型,而且user_id上已经建立索引了,怎么还是查询很慢? test_1的表结构: CREATE TABLE `test_1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` varchar(30) NOT NULL, `name` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_user_id` (`user_id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 查看执行计划,可以看出进行了全表扫描,并没有用上user_id的索引。 mysql> explain select * from test_1 where user_id=1; +----+-------------+--------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows

SQL优化策略

依然范特西╮ 提交于 2020-01-20 15:29:43
策略1.尽量全值匹配 EXPLAIN SELECT * FROM staffs WHERE NAME = 'July'; EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND age = 25; EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND age = 25 AND pos = 'dev'; 策略2.最佳左前缀法则 如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且 不跳过索引中的列 。 策略3.不在索引列上做任何操作 不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描。 EXPLAIN SELECT * FROM staffs WHERE left(NAME,4) = 'July'; 策略4.范围条件放最后 存储引擎不能使用索引中范围条件右边的列 策略5.覆盖索引尽量用 尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select * 策略6.不等于要甚用 mysql 在使用不等于(!= 或者<>)的时候无法使用索引会导致全表扫描 策略7.Null/Not 有影响 注意null/not null对索引的可能影响 策略8.Like查询要当心 like以通配符开头('%abc...'

SQL执行计划参数详细说明

匆匆过客 提交于 2020-01-20 12:50:03
执行计划包含的信息简述 字段 描述 id 执行计划id select_type 查询的类型 table 查询的哪张表 type 访问类型 possible_keys 可能会用到的索引 key 实际使用的索引 key_len 索引中使用的字节数 ref 显示索引的哪一列被使用了 rows 根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数 Extra 包含不适合在其他列中显示但十分重要的额外信息 id:执行计划id select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序 三种情况 id相同,执行顺序由上至下 id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行 id相同不同,同时存在 id相同: id不同: 如果是子查询,id的序号会递增,i d值越大优先级越高,越先被执行 id相同又不同: id如果相同,可以认为是一组,从上往下顺序执行; 在所有组中,id值越大,优先级越高,越先执行 查询类型:select_type 查询的类型,主要是用于区别 普通查询、联合查询、子查询等的复杂查询 查询的表:table 显示这一行的数据是关于哪张表的 type type显示的是访问类型,是较为重要的一个指标,结果值从最好到最坏依次是: system > const > eq_ref > ref > fulltext >

34 到底可不可以使用join?

旧时模样 提交于 2020-01-18 05:09:23
34 到底可不可以使用 join ? 在实际生产中,关于 join 语句使用的问题,一般会集中在以下两类: --1 dba 不让使用 join ,使用 join 有什么问题呢 --2 如果有两个大小不同的表做 join ,应该用哪个表做驱动表呢? 创建 2 个表作为测试 CREATE TABLE `t34` ( `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `a` (`a`) ) ENGINE=InnoDB; drop procedure idata_t34; delimiter ;; create procedure idata_t34() begin declare i int; set i=1; while(i<=1000)do insert into t34 values(i, i, i); set i=i+1; end while; end;; delimiter ; call idata_t34(); create table t35 like t34; insert into t35 (select * from t34 where id<=100) commit; select * from t34; select