数据库优化顺序:Sql及索引->数据库表结构->系统配置->硬件
第一章:Sql语句优化
什么Sql需要进行优化?
使用Mysql慢查日志对有效率问题的SQL进行监控。
1.查看mysql是否开启慢查询日志:show variables like 'slow_query_log';
2.查看超过多长时间的记录到慢查询日志:show variables like 'long_query_time';
如何判断有问题Sql?
1.查询次数多且查询占比大
2.IO大的sql. rows examine 大的
3.未命中的索引sql。rows examine 和rows Send 对比。examin远远大于rows send
如何分析SQL查询?
1.explain返回各列的含义
2.table:显示这一行的数据是关于哪张表的
3.type:这是重要的列,显示连接使用了何种类型。从最好的到最差的连接类型为
4.const/eq_reg/ref/range/index和ALL
5.possiable_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。
6.key:实际使用的索引。如果为Null,则没有使用索引。
7.key_len:使用的索引的长度,在不损失精确性的情况下,长度越短越好。
8.ref:显示索引的哪一列被使用了,如果可能的话,是一个常数。
9.rows:MySql认为必须检查的用来返回请求数据的行数。
具体优化:
1.max():在要max的字段上加索引(执行计划不select直接出结果)
2.count():count(*)会包含null的列,count(字段)不会包含null的列
错误的方式:
select count(date(return_time)='2018-07-02' or date(return_time)='2018-07-03') as count from heatedloan_credit.pay_order;
正确的方式:(利用NULL值不会被计数的特性)
select count(date(return_time)='2018-07-02' or null) as count1,count( date(return_time)='2018-07-08' or null) as count2 from heatedloan_credit.pay_order;
3.子查询:
对子查询尽量用join on 来写,如果有一对多的情况下 要用distinct来去重
4.group by:
如果涉及到表联接的过程中有group by这样的语句,可以先通过group by做为子查询,统 计出结果后,再与其它表进行关联查询。
优化group by 查询后,要在外面加上筛选条件则在子查询中增加
5.limit
imit常用于分页处理,时常会伴随order by从句使用,因此大多时候会使用Filesorts这样 会造成大量的io问题
(1).使用有索引的列或主键进行order by操作
(2).记录上次返回的主键,在下次查询时使用主键过滤
即将:select film_id,description from sakila.film order by film_id limit 50,5;
改为:select film_id,description from sakila.film where file_id >55 and film_id<=60 order by film_id limit 1,5;
使用这种方式有一个限制,就是主键一定要顺序排序和连续的,如果主键出现空缺可能 会导致最终页面上显示的列表不足5条,解决办法是附加一列,保证这一列是自增的并增 加索引就可以了
第二章:索引优化
6.索引优化之添加索引
如何选择合适的索引列?
(1).在where,group by,order by,on从句中出现的列
(2).索引字段越小越好(因为数据库的存储单位是页,一页中能存下的数据越多越好 )
(3).离散度大得列放在联合索引前面
select count(distinct customer_id), count(distinct staff_id) from payment;
查看离散度 通过统计不同的列值来实现 count越大 离散程度越高。建立联合索引的时 候,将离散度更高的索引放在前面index(A,B);A离散度大于B
7.索引优化之重复索引,冗余索引,删除不用索引
索引存在的目的是为了加快查询的效率,不过索引不是越多越好,索引多了不但影响写 入效率,会增加数据库判断使用什么索引来查询的开销,还会增加数据库分析的时间。
有时候也会出现以去掉重复或者无效的索引为优化手段的优化方式。
需要删除的索引:重复索引,冗余索引,不用索引
显示数据库中重复,冗余索引的SQL:
use information_schema;
SELECT a.TABLE_SCHEMA AS '数据名'
,a.TABLE_NAME AS '表名'
,a.INDEX_NAME AS '索引1'
,b.INDEX_NAME AS '索引2'
,a.COLUMN_NAME AS '重复列名'
FROM STATISTICS a
JOIN STATISTICS b ON a.TABLE_SCHEMA = b.TABLE_SCHEMA
AND a.TABLE_NAME = b.TABLE_NAME
AND a.SEQ_IN_INDEX = b.SEQ_IN_INDEX
AND a.COLUMN_NAME = b.COLUMN_NAME
WHERE a.SEQ_IN_INDEX = 1 AND a.INDEX_NAME <> b.INDEX_NAME;
可以根据查询结果来删除相关索引
工具:
第三章:数据库结构优化
8.1数据库的优化之选择合适的数据类型
(1).使用可存下数据的最小的数据类型
(2).使用简单地数据类型,Int < varchar
(3).尽可能使用not null定义字段
(4).尽量少用text,非用不可最好分表
(5).使用int存储日期时间,:
时间转时间戳:插入数据是时间格式转化为int:unix_timestamp("2016-08-01 13:14:00");
时间戳转时间:查询的时候将int转化为时间格式:fromm_unixtime(1508076155)
(6).ip地址存储可用 bigint (只需要使用7个字节)
ip地址转bigint存储:inet_aton("192.168.168.168")
bigint转ip地址查询:inet_ntoa(3232278696)
8.2数据库的优化之第三范式
遵循表的范式化即数据库设计的规范化,数据表不存在非关键字段对任意关键字段的传 递函数依赖,则符合第三范式。
可以将一张数据表进行拆分,来满足第三范式的要求。
设计表的时候符合范式化是为了:减少数据冗余、减少表的插入、更新、删除异常
设计表的时候使用反范式化是为了:以空间换时间、增强代码的可编程性和可维护性
不符合第三范式要求的表存在以下问题:
(1).数据冗余:(分类、分类描述)对于每一个商品都会进行记录
(2).数据插入异常
(3).数据更新异常
(4).数据删除异常
8.3.数据库的优化之反范式化:为了查询效率,适当增加冗余,少关联表,以空间换时间
8.4数据库的优化之表的垂直拆分:解决表的宽度问题
(1).不经常用得放在同一个表中
(2).经常用得放在同一个表中
(3).大的字段单独放在一个表中
比如:商品表(商品编码,商品名称,商品描述,商品图文详情,商品价格,商品数 量,商品库存)等等
因为,商品图文详情是非常大的数据,一般用text类型。使用频率相较于商品价格和库存 小,那么可以拆分到另一张表中,叫商品详情表(商品编码,商品图文详情)等等字段
8.4数据库的优化之表的水平拆分:解决表的量的问题
常用的拆分方法为:
(1).以订单表为例,对user_id进行hash运算,如果需要拆分成5个表,则使用 mod(user_id,5)取出0-4个值。
(2).针对不同的hashId把数据存到不同的表中
(3).按照数据的创建时间按照年月日来拆分
挑战:
(1).跨分区表进行数据查询
(2).统计及后台报表操作(前后台业务分离,前台查询分表的数据,后台要执行报表操作 则把数据统一到汇总表再操作)
其他关于系统配置优化,第三方工具使用,服务器硬件优化,此篇就不做了解啦~~~