zoukankan      html  css  js  c++  java
  • MySQL优化思想与优化实践

    一、优化思想

    • 硬件优化
    • 软件优化
    • my.cnf参数优化
    • SQL语句优化
    • 架构优化

    1、硬件优化

    硬件优化包括CPU、内存、硬盘、网卡的优化。一般的CPU可以使用2-4核,内存32G-64G,这样可以跑2个实例。

    2、软件优化

    操作系统使用x86_64系统。

    3、my.cnf参数优化

    [mysqld]
    user = root
    port = 3306
    socket = /data/3306/mysql.socket
    basedir = /application/mysql
    datadir = data/3306/data # 数据目录
    open_files_limit = 2000 #MySQ需要打开的文件描述符数量,默认为1024
    back_log = 600  # back_log值指出在MySQL暂时停止回答新请求之前的短时间内多少个请求可以被存在堆栈中。也就是说,如果MySql的连接数达到max_connections时,新来的请求将会被存在堆栈中,以等待某一连接释放资源,该堆栈的数量即back_log,如果等待连接的数量超过back_log,将不被授予连接资源。
    max_connections = 2000 #MySQL最多连接数量
    max_connect_errors = 20 #一个MySQL中与安全有关的计数器值,它负责阻止过多尝试失败的客户端以防止暴力破解密码的情况,默认为10,当尝试连接服务端10次失败后就会报错阻止,重置此值通过重启服务端或者客户端执行FLUSH HOSTS
    table_open_cache = 10 #用于设置table高速缓存的数量。当某一连接访问一个表时,MySQL会检查当前已缓存表的数量。如果该表已经在缓存中打开,则会直接访问缓存中的表已加快查询速度;如果该表未被缓存,则会将当前的表添加进缓存并进行查询。
    max_allowed_packet = 20M #server接受的数据包大小,默认值为1048576(1M)
    sort_buffer_size = 1M #加速ORDER BY 或者GROUP BY 操作,它针对单个线程的,所以当多个线程同时进行排序的时候,系统中就会出现多个sort buffer
    join_buffer_size = 2M #增大join_buffer_size参数使全连接加快
    thread_cache_size = 300 #MySQL服务缓存以重用的线程数,如果有客户端断开连接后再次连接到MySQL服务且线程在缓存中,则MySQL服务会优先使用缓存中的线程
    thread_stack = 200KB #每个连接线程被创建时,MySQL给它分配的内存大小。当MySQL创建一个新的连接线程时,需要给它分配一定大小的内存堆栈空间,以便存放客户端的请求的Query及自身的各种状态和处理信息。
    query_cache_size = 10M #为查询结果所分配的缓存,默认这个参数是没有开启
    query_cache_size = 1M    # 指定单个查询能够使用的缓冲区大小,默认值为1M
    query_cache_min_res_unit = 4M #查询缓存所分配的最小块的大小。默认值是4096(4KB)
    tmp_table_size = 200M #内部内存临时表的最大内存。这个参数不会应用到用户创建的MEMORY表。如果内存临时表的大小超过了这个参数的值,则MySQL会自动将超出的部分转化为磁盘上的临时表。
    max_heap_table_size = 200M #定义了用户可以创建的内存表(memory table)的大小.这个值用来计算内存表的最大行数值
    long_query_time = 2 #设置查询sql语句执行的时间
    log-slow-queries = /data/3306/slow-log.log #记录超过long_query_time设置时间的sql查询语句
    log-error = /data/3306/error.log #错误日志记录路径
    pid-file = /data/3306/mysql.pid
    log-bin = /data/3306/mysql-bin #开启binlog
    relay-log = /data/3306/relay-bin #一般用于主从复制,从服务器的SQL线程读取relay-log应用到服务器与主服务器数据保持一致
    relay-log-info-file = /data/3306/relay.log
    binlog_cache_size = 1M #为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存
    expire_logs_days = 7 #设置日志过期时间为7天
    key_buffer_size = 32M  #指定索引缓冲区的大小,它决定索引处理的速度,尤其是索引读的速度
    read_buffer_size = 1M #是MySQL读入缓冲区大小。对表进行顺序扫描的请求将分配一个读入缓冲区,MySQL会为它分配一段内存缓冲区。read_buffer_size变量控制这一缓冲区的大小。如果对表的顺序扫描请求非常频繁,并且你认为频繁扫描进行得太慢,可以通过增加该变量值以及内存缓冲区大小提高其性能。
    read_rnd_buffer_size = 1M #这个参数用在MyISAM表和任何存储引擎表随机读所使用的内存。当从MyISAM表中以键排序读取数据的时候,扫描的行将使用这个缓存以避免磁盘的扫描。将这个值设到一个较大的值可以显著提升ORDER BY的性能。然后,这个参数会应用到所有的客户端连接,所有不应该将这个参数在全局级别设为一个较大的值;在运行大查询的会话中,在会话级别增大这个参数即可。
    bulk_insert_buffer_size = 8M #批量插入数据
    innodb_buffer_pool_size = 128M #InnoDB用来缓存它的数据和索引的内存缓冲区的大小。
    innodb_data_file_path = ibdata1:1024M:autoextend #单独数据文件和它们尺寸的路径
    innodb_file_io_threads = 4 #InnoDB中文件I/O线程的数量。正常地,这个参数是用默认的,默认值是4,但是大数值对Windows磁盘I/O有益
    innodb_lock_wait_timeout  = 120 #InnoDB事务在被回滚之前可以等待一个锁定的超时秒数
    innodb_log_buffer_size = 8M #InnoDB用来往磁盘上的日志文件写操作的缓冲区的大小
    innodb_log_file_size = 10M #在日志组里每个日志文件的大小。
    [mysqldump]
    quick
    max_allowed_packet = 20M
    ...

    4、SQL语句优化

    (1)索引优化

    • 通过my.cnf中配置(long_query_time、log-slow-queries)查出慢SQL语句进行优化
    • 慢查询日志分析工具(mysqlsla、mysql-explain-slow-log等工具)定位分析

    (2)拆分复杂SQL语句

    • 子查询
    • JOIN连表查询
    • 表记录上千万

    (3)禁止数据库中计算

    数据库核心功能是用于存储数据而非计算,计算等逻辑在应用程序中去实现

    (4)搜索功能

    对于像... where like '%'之类的语句,不走索引,所以一般不要用MySQL可以使用es之类的专业搜索组件实现

    5、架构优化

    • 业务拆分(有的业务可以是用类似redis这种非关系型数据库实现)
    • 数据库前端加缓存,比如memcached等
    • 数据库集群与读写分离
    • 表记录上千万,拆库拆表

    二、优化实践

    数据库出现问题,表现出的形式可能有很多种,比如网站访问速度很慢,那么应该如何去排查与解决呢?下面只是说明过程,并非真正实例:

    1、查看负载

    [root@hadoop-slave1 support-files]# uptime
     11:33:07 up 20:57,  2 users,  load average: 8.08, 9.03, 9.05

    如果负载很高,说明有问题,此时应该查看是什么进程。

    2、查看进程

    [root@hadoop-slave1 support-files]# top
    
    top - 11:39:10 up 21:03,  2 users,  load average: 0.00, 0.01, 0.05
    Tasks: 220 total,   1 running, 219 sleeping,   0 stopped,   0 zombie
    %Cpu(s):  0.6 us,  0.8 sy,  0.0 ni, 98.6 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
    KiB Mem :   999964 total,    74632 free,   720324 used,   205008 buff/cache
    KiB Swap:  2097148 total,  1950140 free,   147008 used.   107984 avail Mem 
    
       PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND           
      3080 root      20   0 3631320 151860  27536 S   6.0 15.2   2:58.06 gnome-shell       
      1291 root      20   0  357644  30528  11272 S   4.7  3.1   0:40.86 X           

    如果查看出MySQL进程cpu等占用太高,此时就应该去查看MySQL了。

    3、查看MySQL线程

    mysql> show full  processlist;
    +----+------+-----------+------+---------+------+-------+------------------------+
    | Id | User | Host      | db   | Command | Time | State | Info                   |
    +----+------+-----------+------+---------+------+-------+------------------------+
    |  4 | root | localhost | NULL | Query   |    0 | NULL  | show full  processlist |
    +----+------+-----------+------+---------+------+-------+------------------------+
    1 row in set (0.00 sec)

    如果看到此处有大量线程等待,并且有执行的SQL语句,那么应该看看这条SQL语句是怎么回事。

    4、SQL语句解析

     主要查看是否利用了索引的情况:

    mysql> explain select * from userinfo where username='张三'G;
    *************************** 1. row ***************************
               id: 1
      select_type: SIMPLE
            table: userinfo
             type: ALL
    possible_keys: NULL
              key: NULL
          key_len: NULL
              ref: NULL
             rows: 3
            Extra: 
    1 row in set (0.00 sec)

    像上面这种possible_keys、key、NULL、ref都是NULL显然是没有利用上任何索引。所以应该尝试添加索引进行优化。

  • 相关阅读:
    pwnable.kr之input
    pwnable.kr之bof
    pwnable.kr之fd
    运维及服务器组成详解
    查看锁信息(开启InnoDB监控)
    【原创】记一次MySQL大表高并发写入引发CPU飙升的排障过程
    【原创】获取MySQL crash 时的core file
    【原创】MySQL Replay线上流量压测工具
    python面向对象
    TCP三次握手与四次挥手
  • 原文地址:https://www.cnblogs.com/shenjianping/p/13734251.html
Copyright © 2011-2022 走看看