zoukankan      html  css  js  c++  java
  • Mysql优化

    1.表结构的优化
    选择合适的数据库类型
    数据库类型的选择,终点在于合适二字,如何确定选择的数据类型是否合适?
    1.使用可以存下你的数据的最小的数据类型。
    2.使用简单的数据类型。Int要比varchar类型在mysql处理上简单
    3.尽可能的使用not null定义字段。
    4.尽量少用text类型,费用不可时最好考虑分表。
    使用int来存储日期时间,利用FROM_UNIXTIME(),UNIX_TIMESTAMP()两个函数来进行转换
    FROM_UNIXTIME 时间戳转换为正确的时间格式
    UNIX_TIMESTAMP 正确的时间格式转换为时间戳
    CREATE TABLE test(
    id INT AUTO_INCREMENT NOT NULL,
    timestr INT,
    PRIMARY KEY(id)
    );
    INSERT INTO test (timestr) VALUES (UNIX_TIMESTAMP('2018-11-08'));
    SELECT FROM_UNIXTIME(timestr) FROM test;
    使用bigint来存储ip地址,利用 INET_ATON(),INET_NTOA()两个函数来进行转换
    INET_ATON ip地址到整形
    INET_ATOA 整形到ip地址
    CREATE TABLE sessions(
    id INT AUTO_INCREMENT NOT NULL,
    ipaddress BIGINT,
    PRIMARY KEY(id)
    );
    INSERT INTO sessions(ipaddress) VALUES (INET_ATON('127.0.0.1'));
    SELECT INET_ITOA(ipaddress) FROM sessions;
    多数情况下可能使用varchar来进行存储因为他明显是一个字符串
    mysql中还有另外一个选择使用bigint来存储ip地址
    如果存储一个完整性的ip地址的话使用varchar大约需要15个字节
    如果使用bigint的话他只需要8个字节这样的话相差大概7个字节
    表的范式化优化
    范式化是指数据库设计的规范,目前说到范式化一般指第三设计范式,也就是要求数据表中不存在非关键字字段对任意候选关键字端的传递函数依赖则符合第三范式
     
    商品名称
    价格
    重量
    有效期
    分类
    分类描述
    可乐
    3.00
    250ml
    2018.12
    酒水饮料
    碳酸饮料
    苹果
    3.00
    250ml
    2019.02
    生鲜食品
    碳酸饮料
     
    存在以下传递函数依赖关系
    (商品名称)->(分类)->(分类描述)
    也就是说存在非关键字段 “分类描述” 对关键字段 “商品名称” 的传递函数依赖。
    对于不符合第三范式要求的表为何说它的结构并不够优化是因为它存在的一些问题
    不符合第三范式要求的表存在下列问题
    1.数据冗余:(分类,分类描述)对于每一个商品都会进行记录
    2.数据的插入异常
    3.数据的更新异常
    4.数据的删除异常
    如何把这张表转换成符合第三设计范式要求通常情况下都需要拆分
    商品名称
    价格
    重量
    有效期
    可乐
    3.00
    250ml
    2018.12
    苹果
    9.00
    500kg
    2019.02
     
    分类
    分类描述     
    酒水饮料
    碳酸饮料
    生鲜食品
     水果 
     
    分类
    商品名称
    酒水饮料
    可乐
    生鲜食品
    苹果
    表的反范式优化
    反范式化是指为了查询效率的考虑吧原本符合第三范式的表适当的增加冗余,以达到优化查询效率的目的,反但是话是一种以空间来换取时间的操作。
     
    用户表
    用户ID
    姓名
    电话
    地址
    邮编
    订单表
    订单ID
    用户ID
    下单时间
    支付类型
    订单状态
    订单商品表
    订单ID
    商品ID
    商品数量
    商品价格
     
    商品表
    商品ID
    名称
    描述
    过期时间
     
     
    这四张表是完全符合第三范式要求的,如果在这种情况下我们要查出订单的基本信息
    SELECT B.用户名,B.电话,B.地址,A.订单ID,SUM(C.商品价格*C.商品数量) AS 订单价格
    FROM 订单表 AS A
    LEFT JOIN 用户表 AS B ON A.用户ID = B.用户ID
    LEFT JOIN 订单商品表 AS C ON C.订单ID = B.订单ID
    GROUP BY B.用户名,B.电话,B.地址,A.订单ID
     
    反范式化是指为了查询效率的考虑吧原本符合第三范式的表适当的增加冗余,以达到优化查询效率的目的,反但是话是一种以空间来换取时间的操作。对下面的表进行反范式化后
    用户表
    用户ID
    姓名
    电话
    地址
    邮编
     
     
     
     
    订单表
    订单ID
    用户ID
    下单时间
    支付类型
    订单状态
    订单价格
    用户名
    电话
    地址
    订单商品表
    订单ID
    商品ID
    商品数量
    商品价格
     
     
     
     
     
    商品表
    商品ID
    名称
    描述
    过期时间
     
     
     
     
     
     
    反范式后再查询订单信息
    SELECT A.用户名,A.电话,A.地址,A.订单ID,A.订单价格
    FROM 订单表 AS A
    表的垂直拆分
    所谓的垂直拆分,就是吧原来一个有很多列的表拆分成多个表,这解决了表的宽度问题。通常垂直拆分可以按胰腺癌原则进行:
    1.吧不常用的字段单独存放到一个表中。
    2.把大字段独立放到一个表中。
    3.吧经常一起使用的字段放到一起。
     
    CREATE TABLE `film`(
    `film_id` SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
    `title` VARCHAR(255) NOT NULL,
    `descroption` TEXT,
    `release_year` YEAR(4) DEFAULT NULL,
    `language_id` TINTINT(3) UNSIGNED NOT NULL,
    `original_language_id` TINYINT(3) UNSIGNED DEFAULT AULL,
    `rental_duration` TINYINT(3) UNSIGNED NOT NULL DEFAULT '3',
    `rental_rate` DECIMAL(4,2) NOT NULL DEFAULT '4.99',
    `length` SMALLINT(5) UNSIGNED DEFAULT NULL,
    `replacement_cost` DECIMAL(5,2) NOT NULL DEFAULT '19.99',
    `rating` CARCHAR(5) DEFAULT 'G',
    `special_features` CARCHAR(10) DEFAULT NULL,
    `last_update` TIMESTAMP,
    PRIMARY KEY(`film_id`)
    )ENGINE=INNODB DEFAULT CHARSET=utf8
    首先来说他又两个比较大的字段 title(标题)  descroption(描述) 在查询过程中实际上很少使用descroption这种大列 而title和descroption又经常在一起使用所以就需要把这两个列单独提出来添加到附加表中
    拆分之后的表
    CREATE TABLE `film`(
    `film_id` SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
    `release_year` YEAR(4) DEFAULT NULL,
    `language_id` TINTINT(3) UNSIGNED NOT NULL,
    `original_language_id` TINYINT(3) UNSIGNED DEFAULT AULL,
    `rental_duration` TINYINT(3) UNSIGNED NOT NULL DEFAULT '3',
    `rental_rate` DECIMAL(4,2) NOT NULL DEFAULT '4.99',
    `length` SMALLINT(5) UNSIGNED DEFAULT NULL,
    `replacement_cost` DECIMAL(5,2) NOT NULL DEFAULT '19.99',
    `rating` CARCHAR(5) DEFAULT 'G',
    `special_features` CARCHAR(10) DEFAULT NULL,
    `last_update` TIMESTAMP,
    PRIMARY KEY(`film_id`)
    )ENGINE=INNODB DEFAULT CHARSET=utf8
    CREATE TABLE `film`(
    `film_id` SMALLINT(5) UNSIGNED NOT NULL,
    `title` VARCHAR(255) NOT NULL,
    `descroption` TEXT,
    PRIMARY KEY(`film_id`)
    )ENGINE=INNODB DEFAULT CHARSET=utf8
     表的水平拆分
    表的水平拆分是为了解决表单的数据量过大的问题,水平拆分的表每一个表的结构都是完成一致的。一下面payment表为例
    CREATE TABLE `payment`(
    `payment_id` SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
    `customer_id` SMALLINT(5) UNSIGNED NOT NULL,
    `staff_id` TINYINT(3) UNSIGNED NOT NULL,
    `rental_id` INT(11) DEFAULT NULL,
    `amount` DECIMAL(5,2) NOT NULL,
    `payment_data` DATETIME NOT NULL,
    `last_update` TIMESTAMP,
    PRIMARY KEY(`payment_id`)
    ) ENGINE=INNODB DEFAULT CHARSET=utf8
    水平拆分就是表中数据量的问题,加入表中数据量达到了上亿条,那么这时候我们在查询的情况下尽管加上了完美的索引查询效率可能也会非常低,并且写入效率可能也会相对的慢。那么这个时候我们就需要考虑表的水平拆分,水平拆分之后每一张表的表结构都是相同的,加入说要对payment表进行拆分的话那么创建的就是payment_1 payment_N表结构都是跟现在的结构都是一样的。
     
    需要解决的问题是我们如何平均分到每一张表
    常用的水平拆分方法为:
    1. 对customer_id进行hash运算,如果要拆分5个表则使用mod(customer_id,5)取出0-4个值
    2. 针对不同的hashID吧数据存到不同的表中。
    挑战
    1.跨区分表进行数据查询
    2.统计及后台报表操作
    2.服务器硬件优化
    如何选择CPU
    思考 : 是选择单核更快的CPU还是选择核数多的CPU?
    1.Mysql有一些工作只能使用到单核CPU
    Replicate , SQL…….    一个SQL的执行   复制
    2.MySql对CPU核数的支持并不是越多越快
    MySQL5.5使用的服务器不要超过32核
    Disk 磁盘 IO优化
    常用RAID 级别简介
    RAID0:也称为条带,就是把多个磁盘连接成一个硬盘使用,这个级别IO最好
    RAID1:也称为镜像,要求至少有两个磁盘,每组磁盘存储的数据相同。
    RAID5:也是吧多个(最少3个)硬盘合并成1个逻辑盘使用,数据读写时会建立奇偶效验信息,并且奇偶效验信息和相对应的数据分别存储于不同的磁盘上。当RAID5的一个磁盘数据发生损坏后,利用应用剩下的数据和相应的奇偶效验信息去回复被损坏的数据
    RAID1+0:就是RAID1和RAID0的结合。同事具备两个级别的有点缺点。一般建议数据库使用这个级别。
     
    思考:SNA 和 NAT 是否适合数据库?
    1.常用于高可用解决方案。
    2.顺序读写效率很高,但是随即读写不如人意。
    3.数据库随即读写比率很高
    3.操作系统配置优化
    系统优化分两种
    操作系统的优化
    mysql系统本身的优化
    因为数据库是基于操作系统运行的,操作系统的一些限制同样也会限制数据库的限制
    比如在之前32位系统中就限制了内存大小已经最大的文件的大小这个时候mysql数据库也会受到这种限制,对于操作系统来说目前基本都运行在64位操作系统下,对32位操作系统基本上不太重视,但是操作系统中可能还有其他的一些限制也会影响到数据库
     
    数据库是基于操作系统的,目前大多数MySQL都是安装在Linux系统之上,所以对于操作系统的一些参数配置也会影响到Mysql的性能,下面就列出一些常用到的配置。
    网络方面的配置,要修改/etc/sysctl.conf文件
    # 增加tcp支持的队列数
    net.ipv4.tcp_max_syn_backlog = 65535
    # 减少断开连接时,资源回收
    net.ipv4.tcp_max_tw_buckets = 8000
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1
    net.ipv4.tcp_fin_timeout= 10
     
    打开文件数的限制,可以使用ulimit -a 查看目录的各位限制,可以修改/etc/security/limits.conf文件,增加以下内容以修改打开文件数量的限制
    *soft nofile 65535
    *hard nofile 65535
    除此之外最好在MySQL服务器上关闭iptables,selinux等防火墙软件
     
    硬盘分区类型
    MySQL系统优化:
    MySQL可以通过启动时指定配置参数和使用配置文件两种方法进行配置,在大数情况下配置文件位于 /etc/my.cnf 或是 /etc/mysql/my.cnf在windows系统配置文件可以是位于C:/windows/my.ini文件,MySQL查找配置文件的顺序可以通过以下方法获得
    # /usr/sbin/mysqld --verbose --help | grep -A 1'Default options'
    注意 :  如果存在多个位置在配置文件,则后面的会覆盖前面的
     
    innodb_buffer_pool_size
    非常重要的一个参数,用于配置Innodb的缓冲池如果数据库中只有Innodb表,则推荐配置为总内存的75%。
    一下SQL语句是算出系统中每一种引擎表的大小
    SELECT ENGINE,ROUND(SUM(data_length + index_length) / 1024 / 1024, 1) AS "Total MB" FROM INFORMATION_SCHEMA.TABLES WHERE table_schema not in ("information_schema","performance_schema") GROUP BY ENGINE;
     
    innodb_buffer_pool_size >= Total MB
     
    innodb_buffer_pool_instances
    MySQL5.5中新增加参数,可以控制缓冲池的个数,默认情况下只有一个缓冲池。
    指定了我可以吧缓冲池分成多少分,因为在mysql系统中有一些资源是需要独占使用的,缓冲池就是这么一种资源。如果他只有一个缓冲池的话在一定程度上会增加阻塞的频率,因为他是数据请求资源,如果可以把它分成多分的话。我们可以适应的增加一些并发性。一般情况下会把缓冲池分成4份或者8份每一份的大小是用innodb的总大小除以份数这就是每一份的大小
     
    innodb_log_buffer_size
    innodb log 缓冲的大小,由于日志最长每秒钟就会刷新所以一般不太大
    innodb需要先把日志写到日志缓冲区然后在提交到磁盘这是为了他效率的考虑。通常情况下最短也是一秒钟对log进行一次刷新,刷新到磁盘的操作因此 log buffer size这个不会太大只要可以保存一秒以内事务的日志即可
     
    innodb_flush_log_at_trx_commit
    关键参数,对innofb的IO效率影响很大。默认值为1,可以取0,1,2三个值,一般建议设为2,但如果数据安全性比较高则使用默认1
    这个参数决定了数据库是多长时间吧变更刷新到磁盘
    0:我每一次提交是不刷新的 每一秒钟变更刷新到磁盘一次
    1:每一次提交他都会吧文件变更刷新到磁盘 这是最安全的一种方式
    2:每一次提交只是把它刷新到缓冲区 然后么一秒钟吧缓冲区刷新到磁盘
     
    innodb_read_io_threads
    innodb_write_io_threads
    以上两个参数决定了innodb读写的IO进程数,默认为4
    Mysql5.5之后可以人为的调整使用的进程数量,这是可以根据cpu的核数来分别调整他的读和写的IO进程数量,当然还有根据负载,读负载大一些还是写负载大一些来进行区别的调整
     
    innodb_file_per_table
    关键参数,控制innodb每一个表使用独立的空间,默认为OFF,也就是所有表都会简历在共享表空间中
    1.如果所有的innodb表都使用共享表空间的话,首先来说共享表空间他的IO就会成为一个瓶颈,因为大家肯定都是在写入共享表空间的时候都是顺序去写的,那么共享表空间只有一个文件,所以在并发写入的时候他的效率会大大降低
    2.innodb共享表空间他是无法自动收缩的。如果我们删除一个很大的日志表,或者很大一个不是用的表的话我这边想要收缩共享表空间那么只能把所有的数据都导出来之后再导入进去,这样才能对共享表空间进行收缩
     
    建议吧innodb_file_per_table设置为ON 每一个innodb表都适用独立的表空间来进行存储这种情况下如果我们队某一些表来进行删除或者。。。就可以马上回收到这一部分的表所使用的表磁盘空间 另外由于它是分开多个文件那么他就可以增加并发读写的效率
     
    innodb_stats_on_metadata
    决定了MySQL 在什么情况下刷新 innodb 表的统计信息
    数据库优化器如果使用表中的索引它是需要借助一些表的统计信息
    通常情况下需要在一些情况下对这个表的统计信息进行刷新以保持优化器能正确的使用到正确的索引
    如果对数据统计信息频率非常高的话也会影响数据库的性能
    mysql默认情况下在查询系统表。。。。都会对表的统计信息进行刷新 这显然是没必要的所以我们要把这个参数设置为OFF 不让MySQL在这种情况下去刷新表的统计信息 我们需要人为的去找一个非常行的时间段来给表的统计信息进行刷新 这样也可以保持数据库一个良好的性能
    第三方配置工具:
    Percon Configguration Wizard 配置向导只是建议
     
    4.索引优化SQL
    索引优化SQL
    索引并不是越多越好
    通常情况下简历索引可以优化查询效率但是会降低写入效率
    增加索引会有利于查询但是会影响DELECT UPDATE INSERT语句
    实际上往往都不是这样的
    过多的索引不但会影响DELECT UPDATE INSERT效率同时也会影响查询
    MYSQL在执行查询分析的时候首先要选择要使用哪一个索引来进行查询 因为索引越多他的分析结果就越慢同样会提高查询效率
    如何找到重复和冗余
    重复索引指的是相同的列以相同的顺序简历的同类型的索引
    如下表中primary key id 列上的索引就是重复索引
    create table test(
    id int not null primay key,
    name varchar(10) not null,
    title varchar(50) not null,
    unique(id)
    )engine=innodb;
    冗余索引是指多个索引的前缀列相同,或是在联合索引中包含了主键的索引
    下面这个例子中的key(name,id)就是一个冗余索引
    create table test(
    id int not null primay key,
    name varchar(10) not null,
    title varchar(50) not null,
    key(name,id)
    )engine=innodb;
    如何查找重复索引
    1. 在information_schema数据库中查询
    当然这条sql只能解决一部分问题因为他只查他的前缀并没有检查哪些索引是包含主键的
    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
    1. 使用pt-duplicate-key-checker工具检查重复及冗余索引
    pt-duplicate-key-checker -uroot -p '密码' -h 127.0.0.1
    索引维护优化
    重复索引 / 冗余索引之外还有一种索引 那就是无用的索引
    由于业务变更以及表结构的变更,以及表结构的变更。可能会有一些索引我们之前使用到的,一直在使用的但是由于我们业务变更有些索引可能已经不再使用, 如果这些索引一直存在表中,也会影响查询以及写入的效率,因此我们在一些条件允许的情况下要对这些已经不是用的索引进行删除
    索引的维护及优化---删除不用索引
    目前mysql中还没有记录索引的使用情况,但是在PerconMySQL和MariaDB中可以通过INDEX_STATISTICS表来查看那些索引未使用,但是在MySQL中目前只能通过慢查询日志配合pt-index-usage工具来进行索引使用情况的分析
    pt-index-usage -uroot -p'' mysql-slow.log
    如果我们的数据是一主多从的情况下,在不同的从上我们所用到的业务是不一样的,那么我们在搜集慢查询日志的时候就要搜集所有主从的慢查询日志,并且对这些日志进行统计的分析
    这样才能分析出来那些索引是真正不使用的,因为有时候一条索引可能在第一个从上不适用,但在其他从上还是使用的。或者说在主上不适用,但在从上还是使用的,那么这种索引也是需要保留的
    5.语句优化SQL
    LIMIT优化
    LIMIT常用于分页处理,时长会伴随ORDER BY从句使用,因此大多时候会使用Filesorts这样会造成大量的IO问题
    假设 table 表有1000条数据
    EXPLAIN SELECT field1,field2 FROM table ORDER BY field3 LIMIT 50,5;
     TYPE : ALL
     ROWS : 1000
    EXTRA : Using filesort
    以上sql 执行计划来看使用了表扫描的操作 并且扫描了N行的记录并且使用了文件排序的方式 因此在数据量大的情况下会造成很大的IO问题
    优化步骤1 :  使用有索引的列或者主键进行ORDER BY操作
    EXPLAIN SELECT field1,field2 FROM table ORDER BY id LIMIT 50,5;
     TYPE : index
     ROWS : 55
        KEY : PRIMARY
    EXTRA :
    改写之后的SQL执行计划中发现他并没有使用查询计划方式而是使用主键进行主键的排序
    优化步骤2 :  记录上一次返回的主键,在下一次查询时用主键过滤
    EXPLAIN SELECT field1,field2 FROM table WHERE id > xx AND id <= xx ORDER BY id LIMIT 50,5;
     TYPE : range
    POSSIBLE_KEYS : PRIMARY
      KEY : PRIMARY
      KEY_LEN : 2
     ROWS : 5
    EXTRA : Using where
    再一次深度优化之后会发现实际扫描行数只有5行 不管如何更改他的页码他的执行记录是不会变得效率也是固定的
    这种方式有一个缺点他的主键id必须是顺序排序的如果说主键id中间确这几行变会出现返回的数据不足与5行记录
    *避免了大量扫描的数据
    子查询优化
    2018年11月6日
    11:36
    A表
    id
    1
    B表
    id
    1
    通常情况下,需要把子查询优化为join查询,但在优化时需要注意关联是否有一对多关系,要注意重复数据
     
    子查询方式查询
    SELECT A.id FROM A WHERE A.id IN (SELECT B.id FROM B);
    返回结果
    id
    1
    使用join优化后的写法
    SELECT A.id FROM A JOIN B ON A.id = B.id;
    返回结果同上
    id
    1
    假如说在B表里面在插入一条id为1的数据此时B表有两条id1的数据
        这种情况下如果使用子查询他仍然返回 一条id为1的数据
    id
    1
    如果使用join的方式查询这时他会返回 两条id为1的数据
    id
    1
    1
    如果说1对多他的查询结果是可能变重复的这时候就使用distinct这个函数来进行去重
    SELECT DISTINCT A.id FROM A JOIN B ON A.id = B.id;
    id
    1
    这是子查询优化成join方式的一个小小的坑
    COUNT和MAX的优化方法
    Max() 通常查询的是最近一条数据或数据中最大的值
    优化方案添加普通索引
    加上普通索引他不需要查询表中的数据只通过索引就可以完全之后sql所执行的结果
    Count()
    Count(*)     包含值为null的列
    Count(field) 不包含null的列
    explain 执行计划
    使用explain查询SQL的执行计划
    # explain 查询语句;
     
    explain 返回各项列的含义
        table : 显示这一行的数据是关于那张表的
         type : 这是重要的列,显示连接使用了各种类型。从最好最差的链接类型为 const、eq_reg、ref、range、index 和 ALL
    const  : 说明他是一个常数查找 一般是对于主键 唯一索引查找的 都是const
    eq_reg : 是一种范围性的查找 一般是对于主键 唯一索引查找的 都是eq_reg
    ref    : 比较常见于链接的查询中 比如一个表基于某一个索引的查找
    rangfe : 是基于索引的范围查找
    index  : 通常是对于索引的扫描来进行操作
    all    : 是进行的表扫描
    possible_keys : 显示可能应用在这张表中的索引。如果为空,没有可能的索引。
          key : 实际实用的索引。如果为NULL,则没有使用索引
      key_len : 使用的索引的长度。在不损失精确性情况下,长度越短越好
          ref : 显示索引的那一列被使用了,如果可能的话,是一个常数
         rows : MYSQL认为必须检查的用来返回请求数据的行数
        extra : 列需要注意的返回值
     Using filesort : 看到这个的时候,查询就需要优化了,MYSQL需要进行额外的步骤来发现如何对返回的行排序
      他根据链接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行
    Using temporary : 看到这个的时候,查询就需要优化了,这里,MYSQL需要创建一个临时表来存储结果,这通常
       发生在对不同的列集进行ORDER BY上,而不是GROUP BY上
     慢查询日志发现有问题的sql
    通过慢查询日志发现有问题的SQL
    1.查询次数多且每次查询占用时间长的SQL
    通常为pt-query-digest分析前几个查询
    2.IO大的SQL
    注意pt-query-digest分析中的Rows examine项
    3.未命中索引的SQL
    注意pt-query-digest分析中Rows examine 和 Rows Send 的对比
    慢查询日志工具
    慢查询日志分析 pt-query-digest
    # 输出到文件
    [root@iZbp1akzlq26t30fbsdwh7Z mysql] # pt-query-digest slow-log > slow_log.report
    # 输出到数据库表
    [root@iZbp1akzlq26t30fbsdwh7Z mysql] # pt-query-digest slow.log -review
    h=127.0.0.1,D=test,p=root,P=3306,u=root,t=query_review
    --create-reviewtable
    --review-history t=hostname_slow
    慢查询日志工具
    通过mysql的安装会自带安装上mysqldumpslow
    慢查询日志分析 mysqldumpslow
    [root@iZbp1akzlq26t30fbsdwh7Z mysql] # mysqldumpslow -h
    Option h requires an argument
    ERROR: bad option
     
    # 最简单的使用方式 mysqldumpslow 慢查询日志目录
    Usage: mysqldumpslow [ OPTS... ] [ LOGS... ]
     
    Parse and summarize the MySQL slow query log. Options are
     
    --verbose    verbose
    --debug      debug
    --help       write this text to standard output
     
    -v           verbose
    -d           debug
     
    # -s参数 通过什么方式来排序
    -s ORDER     what to sort by (al, at, ar, c, l, r, t), 'at' is default
                al: average lock time  # 根据锁定时间
                ar: average rows sent  # 根据返回行数
                at: average query time # 根据返回时间
                 c: count
                 l: lock time
                 r: rows sent
                 t: query time 
    -r           reverse the sort order (largest last instead of first)
     
    # -t 查看前多少条日志
    -t NUM       just show the top n queries
    -a           don't abstract all numbers to N and strings to 'S'
    -n NUM       abstract numbers with at least n digits within names
    -g PATTERN   grep: only consider stmts that include this string
    -h HOSTNAME  hostname of db server for *-slow.log filename (can be wildcard),
               default is '*', i.e. match all
    -i NAME      name of server instance (if using mysql.server startup script)
    -l           don't subtract lock time from total time
     
    mysqldumpslow 分析结果
     
    [root@iZbp1akzlq26t30fbsdwh7Z mysql]# mysqldumpslow mysql-slow.log -t 2 -s al
    Reading mysql slow query log from /var/lib/mysql/iZbp1akzlq26t30fbsdwh7Z-slow.log
    -- count 执行次数
    -- time 执行时间
    -- lock 锁定时间
    -- rows 返回条数
    -- root[root]@localhost  通过那个用户执行的
    Count: 5  Time=0.00s (0s)  Lock=0.01s (0s)  Rows=5.0 (25), root[root]@localhost
      SHOW COLUMNS FROM `yp_area`
    慢查询日志开启
    使用MySql慢查询日志对有效问题的SQL进行监控
    ON = 开启
    OFF= 关闭
    # 查看慢查询日志是否开启
    SHOW VARIABLES LIKE 'slow_query_log';
     
    # 查看慢查询日志所存储文件
    SHOW VARIABLES LIKE 'slow_query_log_file';
     
    # 查看是否吧没有使用索引的sql慢查询日志记录到日志当中
    SHOW VARIABLES LIKE 'log_queries_not_using_indexes';
     
    # 查看超过多少秒的sql记录到日志当中
    SHOW VARIABLES LIKE 'long_query_time';
     
     
    # 设置慢查询日志是否开启
    SET CLOBAL slow_quert_log= on / off
     
    # 设置慢查询日志存储文件
    SET GLOBAL slow_query_log_file='/xxxx/xxxx/xxxx/slow_query_log_file.log'
     
    # 设置吧没有使用索引的sql慢查询存储到日志
    SET GLOBAL log_queries_not_using_indexes= on / off
     
    # 设置超过多少秒之外的sql记录到日志当中
    SET CLOBAL log_query_time = 0.01 (单位是秒)
     
    慢查询日志所包含的内容
    # 执行sql时间
    Time: 2018-11-02T07:23:35.892991Z
     
    # 执行SQL的主机信息
    User@Host: root[root] @ localhost []  Id: 387088
     
    # SQL的执行信息
    Query_time: 0.000155  Lock_time: 0.000057 Rows_sent: 12  Rows_examined: 31
     
    # SQL执行时间
    SET timestamp=1529997815;
     
    # SQL 内容
    SELECT `key`,`value` FROM `yp_setti
  • 相关阅读:
    【官网翻译】性能篇(四)为电池寿命做优化——使用Battery Historian分析电源使用情况
    【官网翻译】性能篇(三)为电池寿命做优化——概述
    【官网翻译】性能篇(二)通过线程提高性能
    Mybatis+Struts2的结合:实现用户插入和查找
    在安装mysql出现的错误以及解决方法
    关于PHP的内置服务器的使用
    误用.Net Redis客户端CSRedisCore,自己挖坑自己填
    dotnet代码管理之密钥分离策略
    dotnetcore三大Redis客户端对比和使用心得
    生产环境(基于docker)故障排除? 有感于博客园三番五次翻车
  • 原文地址:https://www.cnblogs.com/qiaoz/p/10383212.html
Copyright © 2011-2022 走看看