Mysql最佳实践

原创
2014/11/15 10:35
阅读数 367

Mysql最佳实践

本文总结自:

实践:

  • 针对Query Cache优化查询语句。开启MySQL Query Cache是最有效提升性能的方式。如:
// 不会使用cache,因为类似CURDATE, NOW(), RAND()等不确定的函数,MySQL会禁用Query Cache
$r = mysql_query("SELECT username FROM user WHERE signup_date >= CURDATE()");
 
// 会使用cache
$today = date("Y-m-d");
$r = mysql_query("SELECT username FROM user WHERE signup_date >= '$today'");
  • 通过EXPLAIN关键字观察MySQL如何执行查询语句,如:

        

  • 当明确查询的结果为一条时使用LIMIT 1语句,如:

        

  • 尽可能对查询字段进行索引(INDEX)。这也是提升查询性能最简单直接的方式。
  • 使用索引字段进行表JOIN操作。
  • 不要使用Order BY RAND():
// what NOT to do:
$r = mysql_query("SELECT username FROM user ORDER BY RAND() LIMIT 1");
 
 
// much better:
 
$r = mysql_query("SELECT count(*) FROM user");
$d = mysql_fetch_row($r);
$rand = mt_rand(0,$d[0] - 1);
 
$r = mysql_query("SELECT username FROM user LIMIT $rand, 1");
  • 避免使用SELECT *,减轻磁盘操作及网络传输。
  • 总是有一个id字段。通常每个表都有一个id字段:PRIMARY KEYAUTO_INCREMENTUNSIGNED
  • 使用ENUM代替VARCHAR。对于一些字段只有几个特定值,可以选用ENUM类型。
  • 听取PROCEDURE ANALYSE()的建议。通过该语句,可以根据查询结果作出一些分析,比如,若表中的id(INT)值比较小,就会建议使用MEDIUMINT,若某VARCHAR字段的值只有几种,则会建议使用ENUM。
  • 能不用就不用NULL。NULL也会占用额外的空间,MySQL中这样描述NULL:

        

  • 使用Prepared Statement。这不仅利于性能,而且还有安全(防止SQL注入)。虽然你会对Prepared Statement语句传入多个不同的值,但是MySQL只会解析一次SQL语句。
  • 使用UNSIGNED INT存储IP地址,而不是VARCHAR或CHAR。前者只用4个字节,而且你可以通过INET_ATON()INET_NTOA()来转换。
  • 固定长度的表更快。只有表中没有包含任何VARCHAR, TEXT, BLOB类型的字段,表才是固定的。固定长度的表有利于MySQL更快地查询记录。
  • 垂直分区。如将用户表及其用户信息表分开,将一些不变和易变的字段分开,有利于性能提升。
  • 拆分大批量的DELETEINSERT语句。大批量的添加删除操作会影响查询性能,可以进行拆分成小批量的操作,如:
while (1) {
    mysql_query("DELETE FROM logs WHERE log_date <= '2009-10-01' LIMIT 10000");
    if (mysql_affected_rows() == 0) {
        // done deleting
        break;
    }
    // you can even pause a bit
    usleep(50000);
}
  • 尽可能使用更小的数据类型。更小的列将使用更少的磁盘,这对数据库的性能提升也是很重要的。
  • 选择正确的存储引擎。对应业务需求,选择最适合的存储引擎,如,InnoDBMyISAM
  • 调整OS limits参数十分重要:

        

  • 选择使用其他的malloc库。一些malloc库针对多核环境作了优化:

        

  • 设置CPU亲和力(affinity)。通过taskset命令设置CPU亲和力:

        

  • 选择正确的文件系统:

        

  • Mount选项:

        

  • 选择最好的I/O调度算法:

        

  • 多个磁盘上负载均衡:

        

  • 当单线程瓶颈,且对于低并发系统时,关掉Query Cache:

        

        可通过以下语句查看:

SELECT 
	EVENT_NAME AS nm,
	COUNT_STAR AS cnt,
	sum_timer_wait,
	CONCAT(ROUND(sum_timer_wait / 10000000000000, 2), ' s') AS sec
FROM 
	performance_schema.events_stages_summary_global_by_event_name
WHERE
	COUNT_STAR > 0
ORDER BY 
	SUM_TIMER_WAIT DESC
LIMIT
	20;
  • 使用线程池
  • 配置表缓存

        

  • 线程缓存

        

  • 减少每个线程的内存占用:

        

  • 设置sync_binlog=1:

        

  • 设置表引擎为InnoDB

        

  • 使用较大的缓冲池innodb_buffer_pool_size:

        

  • 减少缓冲池竞争:

        

  • 使用更大的redo log,有利于写性能:

        

  • 调整I/O能力

        

  • 配置InnoDB日志刷新

        

  • 开启innodb_file_per_table:

        

  • 配置线程并发性

        

  • 降低事务隔离性

        

  • 合理设计表:

        

  • 降低rows_examined:

        

  • 降低rows_sent

        

  • 降低锁操作:

        

  • 分析slow query log

        

  • 使用performance_schema,使用ps_helper

        

  • 调优备份线程
        
  • 避免磁盘上的临时表:
                 
  • 在应用中缓存数据:
        
  • 避免长时间运行的事务

        

  • 关闭空闲的连接:

        

  • 关掉prepared_statements

        

  • 配置Connector/J

        

            

  • 优化表和数据文件:
        

不吝指正。        

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
2 收藏
0
分享
返回顶部
顶部