美文网首页
MySQL 优化

MySQL 优化

作者: Audience0 | 来源:发表于2019-03-02 14:35 被阅读0次

    一、sql执行顺序
    (1)from
    (3) join
    (2) on
    (4) where
    (5)group by(开始使用select中的别名,后面的语句中都可以使用)
    (6) avg,sum....
    (7)having
    (8) select
    (9) distinct
    (10) order by
    (11) limit

    数据库优化:
    1>数据库设计--三大范式
    2>数据库索引
    3>分表分库(水平分割,垂直分割)
    4>读写分离
    5>存储过程(模块化编程,可以提高速度)
    6>对MySQL配置优化(配置最大并发数my.ini,调整缓存大小)
    7>SQL调优
    8>定时清除不需要的数据,定时进行碎片整理


    三大范式:
    1>对属性的原子性约束,要求属性具有原子性,不可再分解.
    2>对记录要求有唯一性,通常设计一个主键来实现,主键不能包含业务逻辑.
    3>对字段冗余性约束,要求字段没有冗余.


    慢查询:MySQL默认设置10s没有返回结果的,属于慢查询,并存到日志中(在my.ini可以指定慢查询日志目录).
    datadir=" C:/ProgramData/MySQL/MySQL Server 5.5/Data/"


    索引:
    show index from tablename; 查询表的索引
    1>聚簇索引(聚集索引):
    聚簇索引不算是一种单独的索引类型,而是一种数据存储的方式,InnoDB的聚簇索引实际上在B-tree结构上不仅保留了索引还保留了数据行.如下图所示:


    图片.png

    聚簇(聚簇表示数据行和相邻的键值紧凑的存储在一起)索引的每一个叶子节点都包含了主键值,事物ID,用于事物的回滚指针以及所有剩余列即记录行.

    因为无法同时把数据行存放在两个不同的地方,所以一个表只有一个聚簇索引.

    一般默认主键作为聚簇索引,但是如果一张表没有定义主键,InnoDB则会选择一个唯一的非空索引代替.如果也没有这样的索引,InnoDB则会隐式的定义一个主键来作为聚簇索引.InnoDB只聚集在同一个页面中的记录.包含相邻键值的页面可能会相距甚远.

    聚簇索引的优点:
    >数据访问比一般索引更快.因为记录行与主键key存放在一起.
    聚簇索引的缺点:
    >插入速度严重依赖插入顺序.如果不是按照主键的顺序插入的话,那么插入需要重新维护聚簇索引,不仅维护索引还要维护数据行的顺序.更糟糕的是,如果该数据页已满,却还要在插入数据时,这时候会造成页分裂的情况,会导致存储不连续,也会占用更多的磁盘空间,这样全表查询就慢了.

    切记不要用不连续的值做聚簇索引,比如说UUID

    2>非聚簇索引:
    非聚簇索引,也就是该表中除聚簇索引之外的索引,这些索引页称为二级索引.
    二级索引,同样采用B-Tree的结构,但是其叶子节点中存储的是该索引对应的主键或者说聚簇索引的值.如下图所示


    图片.png

    因为二级索引中保存的是聚簇索引的键值,所以,采用二级索引查询时,需要先通过二级索引获取到聚簇索引的键值,在根据聚簇索引的键值获取记录,所以相当于进行两次索引查询.

    3>其他索引概念
    1>主键索引
    ALTER TABLE tablename ADD PRIMARY KEY (字段);
    ALTER TABLE tablename DROP PRIMARY KEY;
    其也是一种唯一索引
    2>唯一索引
    索引列的值,需要唯一
    ALTER TABLE tablename ADD UNIQUE [索引的名字] (字段)
    3>单列索引
    以一个字段作为索引列
    CREATE INDEX 索引的名字 ON tablename (字段);
    ALTER TABLE tablename ADD INDEX 索引的名字 (字段)
    DORP INDEX 索引的名字 ON TableName;
    4>组合索引
    以多个字段联合在一起作为索引.
    5>前缀索引
    前缀索引是以该字段前面一部分作为索引,以减少索引的长度,降低索引存储空间和提高索引效率。
    对于前缀索引,需要定义索引长度,这个尤为重要,需要制定一个尽量短且区分度高的索引。
    ALTER TABLE tablename ADD KEY(字段(长度));

    6>覆盖索引
      如果一个索引包含所有需要查询的字段的值,我们就称该索引是覆盖索引.
      覆盖索引,因为只需要访问索引,而不用再去访问数据行就能获取到所需数据所以效率较高.
      alter table TableName add index(字段名称(前缀索引长度))
    

    采用索引的优缺点:
    优点:索引大大的减少了全表扫描,提高查询效率
    缺点:影响插入,删除操作效率,同时维护索引,需要内存.


    SQL优化:
    创建索引原则:
    1>对数据量较少的表无须建立索引.
    2>避免对具有较少值的字段或者说重复较多的字段作为索引.
    区分度的公式是count(distinct col)/count(*),区分度越高,效率越高.所以最好创建唯一索引
    3>避免选择大型数据类型的列作为索引,比如说varchar等,这种可以使用前缀索引.
    4>在经常出现在where后的条件字段创建索引
    6>经长出现在GROUP BY , ORDER BY后的字段建立索引.
    7>对经常修改的字段不要创建索引.
    8>尽量扩展索引,而不要新增索引.
    9>删除不再使用或很少使用的索引
    10>对于组合索引,不要组合过多的列,一般在5列以下
    使用索引需注意:
    1>要遵循最左匹配原则
    2>隐式转换导致索引失效,例如 字符串类型为数字时不添加引号
    3>对索引进行运算导致索引失效(+ - * / !)
    4>对于 not in, in, !=, not exist也会导致索引失效
    5>对于like "%_" 百分号在前面也会导致索引失效
    6>or,除非or条件上的字段都为索引,否则只能进行全表查询

    其他优化:
    1>count():返回数据集的行数或者返回某列数据非null的数据数.
    如果期望返回的是数据集的行数,则直接count(),这么写并不会把扩展成所有的字段,而是直接忽略所有的列的值,直接统计所有的行数.效率是很高的
    2>优化关联查询
    ⊙在ON上建立索引时,需要关注表关联的顺序,如果关联顺序是A,B,则只需要在B表上建立索引即可,因为A上建立的索引并不会用到.
    ⊙确保group by 和 order by中的表达式只涉及到一个表中的列,这样才有可能用索引去优化.
    3>group by:分组返回的结果集是排序之后的,所以,如果不需要排序可以通过 order by null来强制不排序,可以降低group by的消耗.
    4>优化Limit分页:limit offset , pageSize
    其实是优化offset,因为使用limit时,其实是扫描了offset+pageSize的数据,最后只返回pageSize的数据.而之前扫描的offset则是无用的操作.
    可以根据主键来分页,即where id>offset and id<offset+pageSize order by id
    或者 where id > offset order by id limit pageSize;
    5> == null 用is null代替


    show status like 'slow_queries' 获取慢查询数量

    执行计划:
    explain 会在查询上设置一个标志,当执行查询时,这个标志会使其返回关于在执行计划中每一步的信息,而不是执行该语句.它会返回一行或多行信息,显示出执行该计划中的每一部分和执行次序.
    执行计划返回信息如下:


    图片.png

    id:表示select所属的行,如果有多条返回,则可以代表select的顺序.
    select_type:显示该查询是简单查询还是复杂查询.
    >简单查询:显示Simple 表示该查询不包含子查询和UNION
    >复杂查询:最外层select显示PRIMATY
    SUBQUERY:子查询(不在from子句中的)
    DERIVED:在from子句中的子查询.
    UNION:在UNION中的第二个和随后的select被标记为UNION
    UNION RESULT:用来从UNION的匿名临时表检索的结果的select被此标志.
    table:表示对应行正在访问哪个表.
    type:关联类型或者访问类型,表示以哪种方式进行查询.以下按效率由低到高排列
    >ALL:全表查询
    >index:这个跟全表扫描一样,只是MySQL扫描表时按索引次序进行而不是行.它的优点是避免了排序;最大的缺点是要承担按索引次序读取整个表的开销.
    >range:范围扫描就是一个有限制的全索引扫描,一般是带有between或者where子句中有> <的查询,不用遍历全部索引.
    >ref:这是一种索引访问(索引查找),它返回所有匹配某一个值的行,然而,它可能会找到多个符合条件的行,因此,它是查找和扫描的混合体.这种发生在非唯一索引或者唯一索引的前缀时,把它叫做ref是因为索引要跟某个值进行比较.
    >eq_ref:使用这种索引查找,MySQL知道最多只返回一条复合条件的记录.这种访问方法可以再MySQL使用主键或唯一索引时看到.它会将他们与某个值进行比较,并且无需匹配范围或在找到匹配后再继续查找.
    >const,system:当MySQL能对查询的某部分进行优化并将其转化成一个常量时,它就会使用这个访问类型.
    >NULL:这种访问意味着MySQL能再优化阶段分解查询语句,在执行阶段甚至用不着再访问表或者索引.
    possible_keys:显示查询可以使用哪些索引.
    key:显示了MySQL决定采用了哪个索引来优化该表的访问.
    key_len:显示了MySQL在索引里使用的字节数.
    ref:显示了之前的表在key列记录的索引中查找值所用的列或常量.
    rows:这一列是MySQL估计为了找到所需的行而要读取的行数

    一般索引要达到range以上.

    存储引擎:myisam/innodb/memory
    MyISAM 和 INNODB的区别

    1. 事务安全(MyISAM不支持事务,INNODB支持事务)
    2. 查询和添加速度(MyISAM批量插入速度快)
    3. 支持全文索引(MyISAM支持全文索引,INNODB不支持全文索引)
    4. 锁机制(MyISAM时表锁,innodb是行锁)
    5. 外键 MyISAM 不支持外键, INNODB支持外键. (在PHP开发中,通常不设置外键,通常是在程序中保证数据的一致)
      6.myisam 需要主要定时进行碎片整理 optimize table tablename
      Memory 存储,比如我们数据变化频繁,不需要入库,同时又频繁的查询和修改,我们考虑使用memory, 速度极快. (如果mysql重启的话,数据就不存在了)

    分表分库:

    垂直拆分:垂直拆分就是要把表按模块划分到不同的数据库中,数据库按模块和功能把表划分出来,趋向于服务化
    水平拆分:水平拆分就是要把一个表按照一定的规则把数据划分到不同的表或数据库中.比如按时间,账号规则,年份,取模算法等.

    分表缺点:1.分页查询困难2.查询非常受限

    解决办法:一般主表存放所有数据,再根据业务进行水平拆分,mycar分表功能.


    MySQL主从复制
    作用:数据库备份,读写分离,高可用,集群.
    主从复制过程:
    1>首先,MySQL主库在事务提交时会把数据库变更作为时间events记录在二进制日志文件Binlog中,MySQL主库上的sync_binlog参数控制Binlog日志刷新到磁盘.
    2>主库推送二进制日志文件Binlog中的事件到从库的中继日志Relay Log ,之后从库根据日志Relay Log重做数据变更操作,通过逻辑复制来达到主库和从库的数据一致.


    图片.png

    DBCP依赖commons-pool对象池,所以需要commons-dbcp.jar , commons-pool.jar
    DBCP的BasicDataSource提供了close()方法,所以再XML配置文件中需要制定destory-method="close",以便Spring正常关闭数据源。

    配置数据源:

    image.png

    相关文章

      网友评论

          本文标题:MySQL 优化

          本文链接:https://www.haomeiwen.com/subject/kyojuqtx.html