Mysql-optimization

原因:
1. 表格划分和结构
逻辑复杂,冗余过多,不定长数据类型过多
2. 索引
缺少索引,过多索引,字符类型索引,过长索引
3. 表容量
单一表格数据量过大,数据文件与索引文件过大
4. 更新频率
单位时间内更新次数过多
5. 查询语句不合理
未使用或不恰当的使用索引,表达式表达错误或逻辑复杂
6. 硬件瓶颈
硬盘、文件系统、CPU、内存、网络连接

解决:
1. 选择合适的存储引擎
myisam : 大量读,大量写; select count(*) 快;  Log(分表、主从); query cache ;  delay_key_writes; 全文检索
innodb : 事务处理; 大量读,大量写; 重负载论坛
2. 索引
类型: 主键、单列、多列、约束(Unique)
索引使用原则: 对同一个查询,mysql 对每个表格只使用一个索引
各引擎索引情况:
myisam : 独立文件,主键 --> Record offset  index --> 主键 entry;使用主键与index查询一样快
innodb : clustered 数据记录按主键排列,主键查询非常快,其它可能比较慢
局限:
通配符、正则表达式、索引统计性差或损坏、结果集大于30%,会做全表扫描
优化:
SHOW INDEX FROM .... \G
ANALYZE TABLE ...
OPTIMIZE TABLE ...
myisamchk table-name
3. 内部查询优化
查询优化器: 读取SQL、分析、优化,降低需要检查的记录数
优化要点:
是否有索引可用?
哪个索引最好?或者对每个表,哪个索引最好?
在JOIN里表的依赖关系,寻找最优的JOIN顺序
4. 检查查询语句
explain [extended]
type : const system eq_ref ref range index  all
possible_keys : 可能的key
key : 实际使用的key
ref  : 与key 比较的列
rows : 大约需要检查的记录数
extra :  using where , using index, using temporary, using filesort
5. 慢查询检查
slow_queries.log # 最频繁出现的语句
6. 检查mysql状态
show [full] processlist;
show status;
show variables [like....];
7. 使用真实数据:
导入日常的备份数据到测试机上

优化要点:
1. 正确使用索引: 查询语句中的条件部分,使用到索引的时候,不要使用到表达式、通配符、格式转换
例如:
select count(*) from t_user
where id + 100  < 10000; # 错误
where name like  '%tom%' # 错误
wehre  date(register_time) = '2013-01-09' # 错误
        按最常用的查询确定主键
短主键
        使用整数类型、固定长度字符串、子字符串做索引
删除冗余索引
2.多列索引: 按索引的字段顺序使用字段
INDEX (a, b, c)
        正确:  WHERE a=1 AND b=2 AND c=3
正确:  WHERE a=1 AND b=2
错误: 
 WHERE b=2 AND c=3
错误:  WHERE b=2
正确: WHERE a=1 ORDER BY b ASC, c ASC
错误: WHERE a=1 ORDER BY c
    3. 排序
order by : 如果出现 using filesort 则: 1) 使用组合索引; 2) 应该按join的第一个表的列排序
4. 查询的字段最好明确,不要使用星号
5. 利用缺省值简化更新
6. 使用全文索引取代like # 这个要怎么实现 ?
7. 有时候使用两个查询,比一个快
8. union 代替 or
9. insert delayed, update delayed
10. alter table .... order by expr1, expr2 ...
11. 缓存数据,批量更新
INSERT INTO mytable (id, login_time, login_ip) VALUES、(101, `2007-02-09 11:01:02`, 1234567890), (102, `2007-02-09 11:02:30`, 2234567890),...
ON DUPLICATE KEY UPDATE
login_time=VALUES(login_time), login_ip=VALUES(login_ip)
12. truncate table 后  analyze table
13. 定期 optimize table
14. JOIN 的顺序  # 这个要怎么理解 ?
错误:  SELECT * FROM a JOIN b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key) WHERE b.key=d.key;
优化 : SELECT * FROM b JOIN a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key) WHERE b.key=d.key;
15. 表格划分与结构
按实际应用划分表格职能、确定表结构
控制列的数目与长度,剔除不必要的冗余列: int --> mediumint ; text --> varchar --> char
对常用的表使用固定长度的数据类型: int datetime char row_format =fixed
常用数据与不常用数据分开: userinfo_base userinfo_ext
对分类型字符串列另表处理,按ID引用: countries, authors .....
不同表中同一信息列要定义为相同的类型与长度
短列名
使用 not null
顺序存储的数据(如 Log),考虑按时间分表
统计数据与log 分开,报告从统计数据做,实时或定期更新统计数据

缓存服务器: memcache  reids 等
优点:
数据网络共享、与其它服务器分享运行,不抢资源、查询速度快、越大内存服务器簇
缺点:
只支持精确查询、内存满后,会覆盖老的记录、运行初期,命中率低
    场景:
频繁使用,但较少更新的数据、不需要数据库保存的临时数据
要点:
所有重要数据必需先写数据库
必需保证数据库数据与内存数据一致
当内存中没有数据时,需要从数据库中加载
设置适当的过期时间
程序中的BUG与注入检查:
不要相信任何输入