数据库相关
一. 索引
什么是索引
索引是存储引擎用于快速找到记录的一种数据结构。
B+树叶子节点指针指向被索引的数据
索引的优点
- 减少了服务器需要扫描的数据行数
- 帮助服务器避免排序和分组,避免创建临时表。
- 能够将相关的数据保存在一起,减少IO次数
B+树索引
- B+树索引的一个特点就是高扇出性,树高为2-4层。
- B+树索引分为聚集索引(也称为主索引)和辅助索引(也称为非辅助索引)。
- B+树节点的大小刚好等于操作系统一页的大小
- B+树的叶子节点是用链表连在一起的。
- 由于B+树的有序性,除了用于查找,还可以用于排序和分组
聚集索引
* 聚集索引把索引和数据保存在同一个B+树中,数据表的行记录就存放在叶子节点中。
* **因为无法把数据行放在两个地方**,每张表只能拥有一个聚集索引。
* InnoDB将通过主键来聚集数据。如果没有主键,InnoDB会选择一个唯一的非空索引代替。如果没有这样的索引,InnoDB会隐式定义一个主键作为聚簇索引。
* 聚集索引的优点:
1. 可以把相关的数据保存在一起,例如实现电子邮箱的时候,可以根据用户的ID来聚集数据,这样只需要从磁盘中读取少数的数据页就能获取某个用户的全部邮件,如果没有使用聚簇索引,每一封邮件都可能导致一次磁盘IO
2. 数据访问很快。聚簇索引将索引和数据保存在同一棵树中,从聚簇索引获取数据通常比在非聚簇索引中查找要快。
* 聚集索引的缺点
1. 更新聚簇索引的代价很高。因为会强制InnoDB将每个被更新的行移动到新的位置。
2. 在插入新行的时候,可能面临“页分裂”的问题。当一个行插入某一个已满的页中时,存储引擎会将该页分裂成两个页面,这样会导致表占用更多的磁盘空间。
辅助索引
- 辅助索引的存在不影响数据在聚集索引中的组织,每张表可以有多个辅助索引。
- 辅助索引的原理跟聚集索引一样,但是叶子节点存放着不是行的所有数据,只是该行的主键。如果用辅助索引查找数据,会首先根据索引值找到主键,然后根据主键在聚集索引中查找对应的完整行数据。这就是回表。
Cardinality
- Cardinality:表示索引中不重复记录数量的预估值,在实际应用中,Cardinality应该接近于表中的行数。
- InnoDB对Cardinality的更新策略是:
- 表中的1/16的数据已经发生变化
- 表中数据发生了20亿次变化
- Cardinality的计算
- 是用采样的方法计算的。随机抽取8个叶子节点,计算每个页中不同记录的数目得到8个数,对这8个数取平均再乘上所有的叶子数。
为什么说B+树比B树更适合数据库索引?
1、 B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,但是B树有,因此B+树节点能容纳更多的键值,能查找更大的范围,树高和查询的次数降低,相对IO读写次数就降低了。
2、B+树的查询效率更加稳定:由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
3、由于B+树的数据都存储在叶子结点中,叶子使用指针相连,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。
哈希索引
哈希索引基于哈希表实现。对于每一行数据,存储引擎会对所有的索引列计算一个哈希码,不同的索引列计算出来的哈希码是不同的。哈希索引把哈希码存储在索引中,哈希表保存着指向每个数据行的指针。
- InnoDB存储引擎会根据表的使用情况自动为表生成哈希索引,不能人为干预是否在一张表上生成哈希索引。
- B+树索引不能找到一个给定键值对应的行,只能找到给定键值对应的行所在的页,然后数据库把页读进内存,再在内存中查找。
缺点
无法用于排序与分组;
只支持精确查找,无法用于部分查找和范围查找
索引的优化
1. 必须为独立的列
在进行查询的时候,索引列不能是表达式的一部分,也不能是函数的参数
2. 联合索引
使用多个列作为条件查询的时候,使用联合索引的性能比多个单列索引要好。对表上的多个列进行索引。联合索引也对键值进行了排序。
3.索引列的顺序
建立联合索引的时候,把选择性强的索引列放在前面。
索引的选择性是指:不重复的索引值和记录总数的比值。最大值为 1,此时每个记录都有唯一的索引与其对应。选择性越高,每个记录的区分度越高,查询效率也越高。
4.前缀索引
对于BLOB,text和varchar这样的字符列,应该使用前缀索引,只索引开始的部分字符,这样可以大大节约索引空间。
前缀长度的选取需要根据索引选择性来确定。
缺点: 无法用前缀索引做order by和group by,也无法用前缀索引做覆盖索引。
5.覆盖索引
从辅助索引中直接得到查询的记录,而不需要查询聚集索引的记录。使用覆盖索引的好处是辅助索引不包含行记录的所有信息,占用空间小,IO次数减少;而且不需要回表操作,减少了IO的次数。
索引使用的条件
- 小型的表没必要,全表扫描效率更高
- 中到大型的表,索引非常有效
- 特大型的表,建立和维护索引的代价很高,需要其他的技术,如分区技术。
二. 查询性能优化
使用 Explain 进行分析
作用
Explain可以用来查看SQL语句的执行效 果,可以帮助选择更好的索引和优化查询语句
语法
例如:explain select * from tableName;
简单的说就是explain关键字后面跟你要检查的SQL语句
比较重要的字段
select_type : 查询类型,有简单查询、联合查询、子查询等
key : 使用的索引
rows : 扫描的行数
优化数据访问
1. 减少请求的数据量
- 只返回必要的列,避免使用select * 语句
- 只返回必要的行,使用limit语句来限制返回的数据
- 缓存重复查询的数据,这样可以避免在数据库中进行查询。
2. 重构查询的方式
2.1 切分大查询
一个大查询如果一次性执行的话,可能一次锁住很多数据、占满整个事务日志、耗尽系统资源、阻塞很多小的但重要的查询。所以我们需要将大查询切分成小查询,每个查询的功能完全一样,每次返回一小部分的查询结果,将一次性的压力分散到一个很长的时间段中。
2.2 分解大的连接查询
这个方法的意思是把单个多表连接查询改成多个单表查询,然后在程序中合并数据
如 : select a.,b. from A a join B b on a.id = b.id
可以替换为:
select a.* from A;
select b.* from B;
然后通过程序把数据合并
优点
- 让缓存更高效。对于连接查询,如果其中一个表发生变化,那么整个查询缓存就无法使用。而分解后的多个查询,即使其中一个表发生变化,对其它表的查询缓存依然可以使用。
- 分解成多个单表查询,这些单表查询的缓存结果更可能被其它查询使用到,从而减少冗余记录的查询。
- 减少锁竞争;查询会锁住单个表较短时间,而不是把所有的表长时间锁着
- 在应用层进行连接,可以更容易对数据库进行拆分,从而更容易做到高性能和可伸缩。
查询本身效率也可能会有所提升。
三. 存储引擎
InnoDB
- MySQL默认的引擎,是事务型的引擎,当需要有它不支持的特性时,才考虑用其他的存储引擎。
- 支持真正的在线热备份,其他存储引擎不支持在线热备份。
- 有四个标准的隔离级别,分别是
隔离级别 | Read Uncommitted | Read Committed | Repeatable Read | Serializable |
---|---|---|---|---|
未解决的问题 | 脏读 | 不可重复读 | 幻读 | 解决所有问题 |
其中InnoDB的默认级别是可重复读。
读脏数据和不可重复读的例子
读脏数据解决:对脏数据设置为加锁访问,如果访问结束后释放锁的话,会导致不可重复读。
不可重复读解决:对数据设置为加锁访问,事务结束后释放锁。
幻读解决:在两行记录的空隙加上锁,阻止新纪录的插入;这个锁称为间隙锁。
MyISAM
- 对于只读数据,或者表比较小,可以容忍修复操作,可以使用它。
- 提供了大量的特性,包括用前缀压缩技术让索引更小,通过数据的物理位置索引被索引的行,InnoDB根据主键索引被索引的行。
- 不支持行锁,只有表锁。但是表在读取的时候可以往表中插入新的记录,叫做并发插入。
- 可以自动执行检查和修复的工作,但是修复操作很慢,可能会导致数据的丢失。
比较
- 事务:InnoDB是事务型的,可以使用Commit和Rollback语句
- 锁的级别:InnoDB支持行级锁,MyISAM只支持表级锁
- 外键:InnoDB支持外键,MyISAM不支持
- 备份:InnoDB支持热备份,MyISAM不支持
- 崩溃回复:MyISAM崩溃后发生损坏的概率比InnoDB要大,恢复的速度慢
- 其他特性:MyISAM支持前缀压缩和根据数据的物理位置索引被索引的列。
四. 切分
http://blog.itpub.net/15498/viewspace-2135342/
五. 复制
主从复制
- 主服务器把数据更改记录记录到二进制日志(binlog)中
- 从服务器把主服务器的二进制日志复制到自己的中继日志中。
- 从服务器重做中继日志的日志,把更改应用到自己的数据库上,达到数据的最终一致性。
读写分离
从图中可以看到,SQL语句并不直接进入到master数据库或者slave数据库,而是进入到
proxy,然后proxy判断这条语句是有关写的语句(包括insert、update、delete)还
是读语句(select),当是写语句的时候,那么proxy将向master所在的服务器发出请
求,同理,如果是读语句的时候,proxy将向slave所在的服务器发出请求。
从服务器可以使用 MyISAM,提升查询性能以及节约系统开销;
增加冗余,提高可用性。
主从服务器之间采用主从复制的方法来同步数据