### 10.6 索引
#### 10.6.1 索引的原理
什么是索引
- 就是建立起的一个在存储表阶段
- 就有的一个存储结构能在查询的时候加速
索引的重要性
- 读写比例:10:1 读的速度就至关重要
索引原理
- block 磁盘预读原理
- for line in f
数据库的存储方式
- 新的数据结构————树
- 平衡树 balance tree - b树
- 每个节点(分支点和节点)不仅存储关键字还存储数据
- b+树:在b树的基础上进行了改良变成b+树:
- 1.分支节点个根节点都不在存储实际的数据了,让分支和根节点能存储更多的索引的信息,就降低了树的高度,所有的实际数据都存储在叶子节点中
- 2.在叶子节点之间加入了双向的链式结构,方便在查询中的范围条件
- mysql当中所有的b+树索引的高度基本都控制在3层
- 什么会影响索引的效率——树的高度
- 1.对哪一列创建索引,选择尽量短的列做索引
- 2.对区分度高的列建索引,重复率超过了10%那么不适合创建索引
聚集索引和辅助索引
- 在innodb中 聚集索引和辅助索引并存的
- 聚集索引--主键(快):数据直接存储在树结构中的叶子节点
- 辅助做引--除了主键之外的所有索引都是辅助索引(慢):数据不直接存储在树种,而是留下一个主键(比如数据前面的id)与其数据链接
- myisam中 只有辅助索引
如何创建索引:create index 索引名字 on 表(字段)
删除索引:drop index 索引名 on 表名字
索引的种类
- primary key 主键 聚集索引 约束的作用:非空+唯一
- unique 自带索引 辅助索引 约束的作用:唯一
- index 辅助索引 没有约束作用
索引是如何发挥作用的
select * from 表 where id =xxx
- 在id字段没有索引的时候效率低
- 在id字段有索引之后,效率高
#### 10.6.2 索引的命中
索引不生效的原因:
- 要查询的数据范围大
- < >= <= !=
- between and
- like
- 结果的范围大,索引不生效
- 如果a
- abc%索引生效,%abc索引就不生效
- 如果一列内容区分度不高,索引页不生效
- 索引列不能再条件中参与计算
- select * from s1 where id*10 = 1000000 索引不生效
- 对两列内容进行查询
- and:
- select * from s1 where id = 1000000 and email = 'eva1000000@oldboy';
- and条件两端的内容,优先选择一个有索引的,并且树形结构封号的,来进行查询
- 两个条件都成立才能完成where条件,先完成范围小的缩小后面的条件的压力
- or :
- or条件的,不会进行优化,只是根据条件从左到右依次筛选
- 条件中带有or想要命中索引,这些条件中的所有列都必须是索引列
- select * from s1 where id =1000000 or email = 'eva1000000@oldboy'
联合索引
在联合索引中如果使用了or条件索引就不能生效
- create index ind_mix on s1(id,email)
- select * from s1 where id = 1000000 and email = 'eva1000000@oldboy';
- select * from s1 where id =1000000 or email = 'eva1000000@oldboy'
最左前缀原则:在联合索引中,条件必须含有在创建索引的时候的第一个索引列(id,name,email),即必须含有id去查询
- select * from s1 where id =1000000; 命中索引
- swlect * from s1 where email = 'eva1000000@oldboy'; 不能命中索引
在整个条件从出现模糊匹配开始的那一刻,索引就生效了(<>%都是模糊索引)
- select * from s1 where id<1000000 and email like 'eva%' 未命中
- select * from s1 where id=1000000 and email like 'eva%' 未命中
什么时候用联合索引:
- 只对a或者abc条件进行索引,而不会对b对c进行单独索引
什么时候使用单列索引:
- 选择一个区分度高的列建立索引,条件的范围尽量小,条件中的列不要参与计算,使用and作为条件的连接符
覆盖索引
- 如果我们使用索引作为条件查询,查询完毕之后,不需要回表查,覆盖索引
- 例如:select id from s1 where id =1000000
- 执行计划:explain select id from s1 where id =1000000
什么是索引合并:
对两个字段分别创建索引,由于sql的条件让两个索引同时生效了,那么这个时候这两个索引就成为了合并索引
### 10.7 数据备份和事务:
在命令行中进行,不是数据库
mysqldump -uroot -p123 day40 > D:\code\day40.sql
事务:
- begin; #开启事务
- select * from emp where id = 1 for update; #查询id值,for update添加行锁;
- update emp set salary=10000 where id = 1; 完成更新
- commit; #提交事务
### 10.8 sql注入
-- 注释掉--之后的语句 万一别人在用户登录的时候在username中输入了这个,相当于注释掉了后面的密码
解决办法:
```python
import pymysql
conn = pymysql.connect(host='127.0.0.1',user='root',password='123',database='day41')
cur = conn.cursor()
username = input('>>>')
password = input('>>>>')
sql = "select * from userinfo where name = %s and password=%s"
cur.execute(sql,(username,password)) #不要自己拼接sql语句,将占位符的处理任务交给execute处理
print(cur.fetchone())
conn.close()
```