http://blog.jobbole.com/24006/

https://www.kancloud.cn/taobaomysql/monthly/140090

https://www.kancloud.cn/taobaomysql/monthly/140090


系统设计原则:


为什么这么做,这么做有什么问题,有没有更好的方案,背后的业务价值支撑点。


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


索引原则:


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;