mysql深入一


系统设计原则:
为什么这么做,这么做有什么问题,有没有更好的方案,背后的业务价值支撑点。

顺便说下,碎片式学习效果不大。

索引原则:
1.避免单行访问
例:100条,100次访问数据库。
2.尽量范围访问,利用顺序访问原则,一个是磁盘顺序访问比较快
3.索引覆盖原则,即要查找的数据如果在查询条件索引中能得到,就不需要访问磁盘
4.特定情况下,可以用冗余来解决查询性能。前提是这个冗余字段更新不频繁

一.字段类型选择

1.1. 小字段选择,日期不要用字符串。

1.2.datetime和timestamp区别:
都只支持空值。
datetime需要8个字节,timestamp需要4个字节。
TIMESTAMP值不能早于1970或晚于2037

timestamp不会存储时区信息,会存在北京时区存入的数据,在美国显示错误问题。
datetime存储时区信息,

timestamp在插入或更新记录时会默认填充timestamp字段为当前数据库系统对应时区时间。

1.3.unsigned选择,可以使相应类型存储正数值多一半。

1.4.varchar和char的选择:
varchar是变长,变长体现在需要额外一个字节或二个字节记录记录字段长度。
所以varchar(64)占用存储空间,在当前数据长度小于等于256时是65位。
缺点更新当前字段后,原先一个页存储不下,这时需要分裂当前页。
mysql页大小为:16k。

char则会使用定长字节,会删除未尾空格。varchar不会。

所以说varchar对应字段最大长度,varchar(1)和varchar(256)的区别,前者需要1个字节存储数据长度,后台需要2个字节。

1.5.blob和text区别:
一个是二进制,一个是字符串。
text最大长度为:2^16-1字节
media text最大长度:2^24-1,
mysql底层存储是以实际字符数为主。

二.mysql增加/修改列引起的问题
采用写时复制,会做以下事情:
a.创建结构一致的表,并增加/修改列
b.锁表,将数据复制到新表
c.删除旧表,新表对外开放

三.mysql数据设计原则
a.用合适大小的字段
b.表设计,根据需求可以适当冗余,解决查询问题
c.系统设计时,要明确系统设计目标,数据量,性能,吞吐量,稳定性几个指标。
系统是什么类型的系统,读多写少这类,还是读少写多。


四.索引深入
mysql使用B+树索引,对比B树优点是:
B+树内部非叶子结点不存储实际磁盘物理地址,而只包含索引关键字。节省内存空间,能够利用局部性原理加载更多的结点到内存(磁盘块为加载单位)。
此外B+树也是由于内部非叶子结点不存储实际磁盘物理结点,所以查找都要找到叶子结点后才能找到数据,相对B树来讲查询时间较稳定。

B*树与B+树区别是:B*树能够有更好的空间利用率。达到这个目的需要做:
内部结点需要有指向兄弟结点的指针。
遇到当前要插入的结点需要分裂时,首先看兄弟结点是否还有空间,有空间则将当前结点部分数据迁到兄弟结点。并插入对应值到这个结点,更新父结点对应兄弟结点的关键字。

mysql innodb的二级索引需要两次B+树索引查找。

除了索引where条件,也要考虑order by排序,如果排序用不上索引会导致fileSort。
通常在不考虑排序的情况下,将选择度高的索引条件放在where条件最左边。
对于用户相关查询,如查询对应订单一定要分页。
where id> 之类的性能好于limit offset,size

myql inndb存在聚簇索引与非聚簇索引之分。
聚簇索引的叶子结点包含数据,因此对于数据查找涉及的磁盘交互只会涉及索引结点。这里聚
非聚簇索引叶子结点包含的主键索引值。

索引扫描分析:
按唯一索引查询,explain出来的type是const。非唯一索引出来的一般是ref。

索引开销:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

排序尽量保证能用到索引,否则会进行fileSort。
例:
create_time,id存在索引,有以下sql:
select * from trade_order where create_time='2017-08-05' order by id ;
这个语句会发生fileSort,当表数据量特别大时会查询缓慢。
解决方案:按照create_time排序,应用层做重复数据过滤。或者建立一个组合索引:id,create_time
用组合索引解决这类问题的fileSort时需要注意:
order by中出现的每一个字段必须在组合索引中,且必须满足最左匹配原则。
如果where条件中组合索引第一列为范围查询,则也不会走索引排序。原因是?

范围查询注意点:
范围查询条件后,mysql不会再做其后面的索引。

五.问题
1.为什么建议使用自增主键
不自增,会导致频繁的B+树页分裂

2.为什么不建议主键过长
主键过长,会使得二级索引叶子结点过大。

3.为什么二级索引叶子结点不保存物理地址
物理地址改变时,需要更改的索引结点会太多。

索引高度:
O(h)=O(log d N)

选择自增主键原因:
如果是随机主键,则可能需要频繁的调整索引树,移动数据,因为主键是聚簇索引,数据本身存储在叶子结点。

六.优化思路
1.语句索引优化

2.建立组合索引

符合最左原则

设组合索引为:
a,b,c

则a,b查找有效,
a,c有效: 这里如果a字段过滤出的集合还是较大,则性能会受影响,可以考虑建立a,c辅助索引

b,c或b等无效。

优化器,会优化顺序。比如:b,c,a,也会走这个组合索引

3.索引选择度


4.建立聚簇索引
前提是当前要建立聚簇索引的列值不能太大。因为索引会占用内存。

5.主键索引不能过大
原因在于非主键索引,都会在叶子结点冗余主键索引

6.查看索引
show index from trade_order_0000;


猜你喜欢

转载自blog.csdn.net/zhaozhenzuo/article/details/77801784