美文网首页
mysql 优化

mysql 优化

作者: 8589068464bc | 来源:发表于2021-02-27 13:46 被阅读0次

    mysql参数设置及建议

    获取配置文件读取顺序

    sudo mysqld --verbose --help | grep -A 1 'Default options'

    -- 设置全局参数
    set global 参数名=参数值
    set @@gloabl.参数名:=参数值
    -- 设置会话参数
    set session 参数名=参数值
    set @@session.参数名:=参数值
    
    

    内存参数

    以下为每个连接使用内存上线参数
    sort_buffer_size 排序内存
    join_buffer_size 连接查询内存
    read_buffer_size 读内存
    read_rnd_buffer_size 索引内存

    innodb_buffer_pool_size:总内存-(每个线程所需内存*连接数)-系统保留内存,重启生效 配置文件或启动参数设置

    key_buffer_size myIsam索引缓存

    I/O

    innodb_log_file_size: 单个事务日志大小(记录一小时事务日志)
    innodb_log_file_in_group: 事务日志文件个数(循环写入,多个对性能无影响可不设置)

    事务日志大小=innodb_log_file_size*innodb_log_file_in_group

    innodb_log_buffer_size: 事务日志缓冲器大小(一般每秒刷新,32M-128M)
    innodb_flush_log_at_trx_commit 事务日志缓存刷新模式

    • 0: 每秒进行一次log写入cache, 并flush log到磁盘
    • 1(默认): 在每次事务提交执行log写入cache, 并flush log到磁盘,最安全,性能差.
    • 2(建议): 每次事务提交, 执行log数据写入到cache, 每秒执行一次flush log到磁盘.

    innodb_flush_method=O_DIRECT
    不缓存不预读, 关闭操作系统缓存

    innodb_file_per_table=1
    1 每个表单独表空间

    innodb_doublewrite = 1
    启用双写缓存,防止数据损坏

    delay_key_write myIsam 控制关键字缓冲的脏块何时刷新到磁盘文件中

    • OFF:最安全选项,性能最差;
    • ON:只对在键表时指定了delay_key_write选项的表使用延迟刷新
    • ALL:注意,如果服务器发生崩溃,且缓存中有块没有写入到磁盘文件中时,会造成MyISAM表索引文件的损坏,需要进行修复(repair table)

    query_cache 查询缓存

    mysql8.0已经删除查询缓存, 8.0之前版本建议关闭
    have_query_cache=no 表示当前版本不支持query_cache
    have_query_cache_type=off 关闭query_cache

    最大连接数

    show variables like '%max_connection%'; -- 查看最大连接数
    
    set global max_connections=1000; -- 设置连接数
    
    show status like  'Threads%';
    
    Threads_connected :这个数值指的是打开的连接数.
    
    Threads_running :这个数值指的是激活的连接数,这个数值一般远低于connected数值.
    
    Threads_connected 跟show processlist结果相同,表示当前连接数。准确的来说,Threads_running是代表当前并发数
    

    安全相关

    expire_logs_days 自动清理binlog.单位是 天
    max_allowed_packet 控制MySql可以接收包的大小,主从一致
    skip_name_resolve 禁用DNS查找,开启这个配置,需要对一些IP进行授权才能访问数据库.

    read_only slave服务器,禁止非super权限的用户写权限

    skip_slave_start 禁用slave自动恢复,奔溃后自动恢复不安全
    一般再从数据库中使用,从数据库中的数据只允许主数据库的进行写的权限.
    这个配置保证了主从数据库的一致性.

    sysdate_is_now 确保sysdate()返回确定性日期建议添加这个参数

    ql_mode 设置mysql所使用的sql模式

    • ONLY_FULL_GROUP_BY

      对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY中出现,那么这个SQL是不合法的,因为列不在GROUP BY从句中

    • NO_AUTO_VALUE_ON_ZERO

      该值影响自增长列的插入。默认设置下,插入0或NULL代表生成下一个自增长值。如果用户希望插入的值为0,而该列又是自增长的,那么这个选项就有用了。

    • STRICT_TRANS_TABLES

      在该模式下,如果一个值不能插入到一个事务中,则中断当前的操作,对非事务表不做限制

    • NO_ZERO_IN_DATE

      在严格模式下,不允许日期和月份为零

    • NO_ZERO_DATE

      设置该值,mysql数据库不允许插入零日期,插入零日期会抛出错误而不是警告

    • ERROR_FOR_DIVISION_BY_ZERO

      在insert或update过程中,如果数据被零除,则产生错误而非警告。如果未给出该模式,那么数据被零除时Mysql返回NULL

    • NO_AUTO_CREATE_USER

      禁止GRANT创建密码为空的用户

    • NO_ENGINE_SUBSTITUTION

      如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常

    • PIPES_AS_CONCAT

      将"||"视为字符串的连接操作符而非或运算符,这和Oracle数据库是一样是,也和字符串的拼接函数Concat想类似

    • ANSI_QUOTES

      启用ANSI_QUOTES后,不能用双引号来引用字符串,因为它被解释为识别符

    其他参数

    sync_binlog 控制mysql 如何向磁盘刷新binlog

    • 默认0 mysql并不会主动刷新有操作系统自己决定刷新
    • 大于0 两次刷新binlog间隔时间
    • 1 代表每次有事务提交就刷新磁盘,建议主db设置为1

    tmp_table_size max_heap_table_size 一起使用
    控制内存表临时表大小, 保存一致,不要太大以防溢出(超过物理内存)

    max_connections 控制允许的最大连接数 一般 2000 更大(根据实际环境决定、服务器配置、网络、、、)

    语句优化

    分析

    查询索引使用次数

    SELECT 
        object_schema,object_name,index_name, count_star, b.`TABLE_ROWS` 
    FROM 
        performance_schema.table_io_waits_summary_by_index_usage a 
    JOIN 
        information_schema.tables b 
            ON a.`OBJECT_SCHEMA`=b.`TABLE_SCHEMA` 
            AND a.`OBJECT_NAME`=b.`table_name` 
    WHERE index_name is not null 
    order by object_schema, object_name;
    

    慢查询日志

    设置
    set global slow_query_log=on;
    set global long_query_time=0;  -- 执行时间阈值,单位秒,最小单位微妙(如:0.001s)
    set global slow_query_log_file='/show.log'; -- 保存位置
    set global log_queries_not_using_indexes=on; -- 记录未使用索引的查询语句
    

    分析工具

    mysqldunmslow
    
    mysqldunmslow -s r -t 10 slow-mysql.log
    
    -s 排序
    c:总次数
    t:总时间
    l:锁时间
    r:总行数
    at al ar: t,l,r 平均数 
    
    -t top 顶部几条
    
    pt-query-digest
    // 安装
    yum install -y perl-CPAN perl-Time-HiRes
    
    pt-query-digest --explain  h=127.0.0.1,u=root,p=p@sdfsa show-mysql.log > result.rep
    
    --explain 是否包含执行计划
    

    实时性能分析

    select * from information_schema.processlist where time > 60; -- time 执行时间 单位s
    

    确定查询处理各阶段所消耗时间

    profile (已经不提倡使用,即将移除 'SHOW PROFILE' is deprecated and will be removed in a future release. Please use Performance Schema instead)

    • set profiling=1 只有session级起作用
    • 执行语句
    • show profiles;查看每个查询消耗总时间
    • show profile for query N; N profiles的query id 查询每个阶段所消耗时间
    • show profile cpu for query N; 查看每阶段cup信息;

    Performance Schema

    use performance_schema;
    
    -- 启动相关监控
    update  performance_schema.`setup_instruments` set enabled='YES', timed='YES' where name like 'stage%';
    update performance_schema.`setup_consumers` set enabled='YES' where name like 'events%';
    
    -- 查询语句执行时间
    select a.`THREAD_ID`, `SQL_TEXT`, c.`EVENT_NAME`, (c.`TIMER_END` - c.`TIMER_START`) /1000000000 as `DURATION (ms)` from 
        events_statements_history_long a
    join threads b on a.`THREAD_ID` = b.`THREAD_ID`
    join events_stages_history_long c on 
        c.`THREAD_ID` = b.`THREAD_ID`
    and
        c.`EVENT_ID` between a.`EVENT_ID` and a.`END_EVENT_ID`
    order by a.`THREAD_ID`, c.`EVENT_ID`;
    

    sql优化

    批量表数据修改

    • 通过存储过程修改
    DELIMITER $$
    use `[DATABASE]`$$ --要修改的 schema
    DROP PROCEDURE IF EXISTS `p_delete_row`
    CREATE DEFINER=`root`@·127.0.0.1· PROCEDURE `p_delete_row`()
    BEGIN
        DECLARE v_rows INT;
        SET v_rows = 1;
        WHILE v_rows > 0; --通过循环分批处理
        DO
            DELETE FROM [table] WHERE id > 9000 AND id < 190000 LIMIT 5000; -- 批量修改语句
            SELECT ROW_COUNT() INTO v_rows;
            SELECT SELLP(5) --执行完一批休息一段时间,保证主从同步
        END WHILE;
    END$$
    DELIMITER;
    
    • 也可通过其他语言程序根据情况修改修改,注意分批和休眠(保证完成主从同步)

    修改表结构

    直接修改表结构会锁表,影响业务,可以通过pt-online-schema-change工具修改
    工具会新建表,通过触发器同步旧表数据,然后删除旧表触发器

    pt-online-schema-change 命令参数

    --user=        连接mysql的用户名
    --password=    连接mysql的密码
    --host=        连接mysql的地址
    P=3306         连接mysql的端口号
    D=             连接mysql的库名
    t=             连接mysql的表名
    --alter        修改表结构的语句
    --execute      执行修改表结构
    --charset=utf8 使用utf8编码,避免中文乱码
    --no-version-check  不检查版本,在阿里云服务器中一般加入此参数,否则会报错
    
    pt-online-schema-change --charset=utf8 --no-version-check --user=${cnn_user} --password=${cnn_pwd} --host=${cnn_host}  P=3306,D=${cnn_db},t=$table --alter 
    "${alter_conment}" --execute
    

    为方便可以用shell脚本

    #!/bin/bash
    table=$1
    alter_conment=$2
    
    cnn_host='127.0.0.1'
    cnn_user='user'
    cnn_pwd='password'
    cnn_db='database_name'
    
    echo "$table"
    echo "$alter_conment"
    pt-online-schema-change --charset=utf8 --no-version-check --user=${cnn_user} --password=${cnn_pwd} --host=${cnn_host}  P=3306,D=${cnn_db},t=$table --alter 
    "${alter_conment}" --execute
    

    not in和<>优化

    not in和<> 尽量改为关联查询
    形如select ... where ... not in (select ... from table)的子查询改为join的关联查询

    统计类sql优化

    sum、count、avg等统计类sql

    对实时性要求不敏感的可以通过定时更新汇总表的方式实现
    对实时性要求高的可以通过缓存增量统计的方式实现,定时写入统计汇总表

    相关文章

      网友评论

          本文标题:mysql 优化

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