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显然是没有利用上任何索引。所以应该尝试添加索引进行优化。

  • 相关阅读:
    OK335x mksd.sh hacking
    Qt jsoncpp 对象拷贝、删除、函数调用 demo
    OK335xS 256M 512M nand flash make ubifs hacking
    Qt QScrollArea and layout in code
    JsonCpp Documentation
    Qt 4.8.5 jsoncpp lib
    Oracle数据库生成UUID
    freemarker得到数组的长度
    FreeMarker中if标签内的判断条件
    freemarker语法
  • 原文地址:https://www.cnblogs.com/shenjianping/p/13734251.html
Copyright © 2011-2022 走看看