《深入浅出mysql》由浅入深思考数据库基础

注:本文都是干货

目录

1、选择合适的存储引擎

2、选择合适的数据类型

3、选择合适的字符集

4、索引设计的原则

5、Mysql分区(开一个博文专门描述)

6、对sql语句性能分析的过程

7、开发人员SQL语句层面的优化:查询优化(重点且简单)

      8、优化数据库对象



1、选择合适的存储引擎


Myisam优点是访问速度快,对事务完整性无要求和select为主的应用可以使用此引擎,缺点是不支持事务和外键
Innodb当前mysql默认引擎:优点是对事务并发都支持的很好,缺点是写的效率低,并且占用更多的磁盘空间以保留数据和索引
Memory:该引擎使用存在于内存中的数据来创建表,优点访问速度非常的快默认使用hash索引,缺点关闭服务数据就会丢失,但是表结构还在,很少用一般做cache


2、选择合适的数据类型


(1)CHAR和VARCAHR
小文本选这个数据类型;这两个数据结构现在性能上差别不大了,注意两点:一是前者是定长字符串,后者是变长字符串(Innodb引擎没有了这个概念,都当做char类型操作,但建议使用varchar原因是在平均占有字节方面varchar更少);二是前者会抹除最末尾的空格。
(2)Text和blog类型
大文本选这个类型;Text存储字符数据,blog可存储二进制数据例如图片
注意:text和blog的记录在大量删除后会留下磁盘碎片;在myisam引擎上删除记录后,数据文件大小不变,此时就产生了磁盘碎片。利用 optimize table XXX来解决磁盘碎片空洞问题。在Innodb引擎上你要确定当前文件的存储的方式是共享空间还是独立空间,若是共享空间,就算使用了上述语句,文件大小也是不变的96K(这个大小与mysql设置的页有关,这个问题还没深入与分析),因此要将表设置为独占空间,方可解决磁盘碎片空洞问题,mysql也建议将其设置为独占空间。
(3)整形数中需要注意的:浮点数和定点数
要求精度高的货币类型:必须使用decimal类型,使用浮点数会损失很多钱(浮点数的四舍五入),注意浮点数的四舍五入及其浮点数的加减和比较问题
(4)日期类型:
Date time Datetime timestamp的异同
Datetime的范围比timestamp更大,Datetime貌似是截止到9999年,timestamp截止到2025年左右,Datetime有时区,timestamp是记录插入时的时间,datetime的插入不在意时间的格式但必须有分隔符号


3、选择合适的字符集


若英文较多或者需要处理各式各样的文字,推荐unicode也就是utf8,8代表字节,因为传输字节流。
若数据库只需要支持一般中文,数据量很大,性能要求也高,应该选择双字节长的中文字符集,比如GBK,gbk较小只占2个字节,utf8则占3个字节,减少了磁盘io


4、索引设计的原则


    (1):搜索频繁的列,最适合的搜索列是在where子句或者连接子句的列。
    (2):使用唯一索引,考虑某列中值的分布,索引的列的基数越大,索引的效果越好,比如出生日期,最先可以设置分区按照月份进行表分区,然后再加索引。
    (3):使用短索引:如果需要对字符串列进行索引
        例如varchar(200)长的字符串,若能保证前十个或者前二十个字符多数值是唯一的,那么就对这十几二十个字节进行索引,不要对整个列进行索引,对整个列索引则会导致索引长度过大,是的磁盘io较多,更短的键值,索引高速缓存就能存储的更多,mysql内存可以容纳更多的值,这样就可以找到更多行而不用读取索引较多块的可能性。
    (4):利用最左索引(下解释)
    (5):不要过度使用索引,索引过多可能使得sql优化器在查找优化的时候消耗更多的时间,也可能使得mysql找不到最好的索引。
    (6):对于innodb存储引擎的表,记录是按照一定的顺序存储的,如果有主键,就按照主键保存,若没有主键,有唯一索引,就按照唯一索引保存,如果都没有则表会自动生成一个内部列,按照这个内部列保存。按照主键或者内部列进行的访问是最快的。所以innodb表最好自己指定主键;innodb表的普通索引会保存主键的值,所以尽可能选择较短的数据类型。
(索引区别):索引中最常使用的是B树索引和哈希索引
btree和hash索引的区别: https://www.cnblogs.com/vicenteforever/articles/1789613.html


5、Mysql分区(开一个博文专门描述)


逻辑上只有一个表,但是存储数据,确实在多个物理分区;在存有大量数据的数据库表必须根据分区键建立分区
重点:分区键;种类很多,日期、id、时间、年份、月份等表中的列
Range分区:下需要区间连续且不能重叠,需要掌握增加删除的操作
List分区:枚举类型的操作,如果需要枚举null则需要明确指出
Column分区:为了解决mysql5.5版本之前range分区和list分区只支持整数分区,而进化range和list的补充,从而可以支持整数、日期、字符串
Hash分区:直接设定分区个数
Key分区:类似于hash分区


6、对sql语句性能分析的过程


通过show status了解各种sql的执行频率
定位执行频率较低的sql语句
通过explain分析低效sql的执行计划
常见访问类型:ALL<index< range< ref< eq_ref< const,system< null
通过show profiles显示运行过的sql,接着通过show profile for query X分析sql,之前需要设置set profiling=1
通过trace分析优化器如何选择执行计划:
打开trace,设置格式为JSON,设置trace最大能够使用的内存大小
①set optimizer_trace=”enabled=on”,end_markers_in_json=on;
②接下来写sql语句
③跟踪sql,通过trace文件进一步了解为什么选A计划不选B计划
select *from information_schema.optimizer_trace


7、开发人员SQL语句层面的优化:查询优化(重点且简单)


①尽量用连接查询代替子查询
因为mysql对子查询的优化做的不是太好。
②尽量少用in
因为in中的常量全部存储在一个数组里面,而且这个数组是排好序的。但是如果数值较多,产生的消耗也是比较大的,如果太大会导致性能降低,原因是in是内外两层循环因此in后面的语句或者集合太大的话总体的查询次数就越多,也降低了性能。
③exist和in的选择:尽量用exist
exist是查询操作有外循环查询和内匹配,但并不在内存之中放着,in是内外两层循环,有一句话表明exist和in的适应范围:大表用exist,小表用in,表大小差不多,两者性能差不多,如果in后的集合是连续的,可以用between and语句优化它。对于性能的分析过程到这个链接:https://www.cnblogs.com/clarke157/p/7912871.html
④多用join语句代替子查询
如果使用了子查询代表内存中会建立临时表,那么若使用join代替,速度会快很多不会建立临时表,若子查询中的字段是索引列的话,那么使用join后速度会更快,join语句之中多用inner join语句,因为inner join内连接语句是等值查询返回的行数更少。
⑤少用or语句
如果where或者子查询之中有索引列和非索引列,那么性能是按照非索引列大部分也就是全表检索,降低了性能,可以使用union集合查询来替代or查询,如果表中的记录是唯一的或者我们不在意重复记录的情况,那么建立使用union all代替,因为union需要将两个或者多个结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的CPU运算,增大资源消耗及延迟。
甚至可以用in代替or
⑥使用select语句请尽量指明字段名
减少*的使用,如果字段名恰巧是索引列,那么性能会更高,原因是这样的检索是type是index类型即引擎采取索引查询。
⑦如果排序字段没有用到索引,就尽量少排序
    Group by设置为null
⑧Where字句字段不要进行null的判断,默认字段not null
    出现对null的判断,代表着引擎放弃了索引查询,查询方式为type=all即引擎进行全表查询。
⑨不建议出现字段进行前缀%的模糊查询,可使用全文索引
    如果查询字段出现%前缀的模糊查询,那么引擎将的type=all,改善方法:可以全文索引尽量全文索引fulltext index,即字段查询的值全部写出来,或者将前缀%去掉,放在后面
⑩查询时合理分页
    每次取下一页,设置limit>上一页最大数,
    取出大于2000的20条记录
    不要使用limit 2000,20
要使用id>2000 limit 20 ,原因是利用最大id限制下一页的起点
 
分页查询
 
修改语句后的查询
 

注:明显看出在不同的条件下,sql优化器采取了不同的措施
⑪分段查询,结果集合并处理
       若 一次如果查询的行数过多,会导致时间过长,性能降低,可以每次查询少量,循环遍历查询,然后将结果集合并处理并展示,达到同样的效果
(12) 避免在where子句中对字段进行表达式操作
(13) 对于联合索引来说,要遵守最左前缀法则

        联合索引例如(1,2,3),将索引效果好的,放在最左边,想要使用索引,必须从最左开始,例如:(1)(1,2)(1,2,3)只有这三种情况才使用了索引,若(2,3,)(2),(1,3)等都不能使用到索引,除非自己本身也设置了索引。

8、优化数据库对象

1:优化表的数据类型

procedure analyse()该函数将对当前应用的表进行分析,提出优化建议,

例如:对表table_name进行分析

select *from table_name procedure analyse();

得到的结果

Field_name:分析的字段

Min_value:记录中最小值

Min_max:记录中最大值

Min_length:字段最小长度

Max_length:字段建议长度,我们要留有1个字节长的冗余,可以优化为int(3)

2、通过拆分提高表的访问效率

myisam引擎:垂直拆分和水平拆分。

垂直拆分:

垂直拆分方法:主键加一些列放一个表,主键加其余列放另一个表。

垂直拆分作用和适用:一些列常用,另一些列不常用,采用垂直拆分,使得数据列变少,一个数据页能放更多的数据,查询时就会减少io次数。

垂直拆分缺点:需要管理冗余列,查询所有数据的时候需要联合(join)操作,降低了查询速度。

水平拆分:

水平拆分方法:根据一列或者多列数据的值把数据行放在两个独立的表。

水平拆分作用和适用:

表很大,分割后可以降低在查询时的数据量和索引页数,同时降低了索引的成熟,提高查询速度;

表中数据具有独立性,例如:表中分别记录各个地区的数据或者不同时期的数据,特别是有些数据常用,有些不常用;

需要把数据放在不同的介质上;

水平拆分缺点:需要管理冗余列,查询所有数据的时候需要联合(join)操作,降低了查询速度。

3、必要的冗余也是需要的,可以降低多表查询的连接操作,加快了查询速度

4、使用中间表提高统计查询速度,特别是在数据量大的时候,建立了中间表后可以在查询字段上设置索引,更加快了查询速度

注:年轻要多看书

猜你喜欢

转载自blog.csdn.net/StrawberryMuMu/article/details/90340000
今日推荐