using filesort 不能利用索引来进行分组或排序,利用filesort算法在内存或者磁盘进行排序
using temporary 先在内存中进行分组,归并等操作,不够利用磁盘
SELECT id FROM table ORDER BY RAND() LIMIT n;
优化成=&get;
SELECT id FROM table t1 JOIN (SELECT RAND() * (SELECT MAX(id) FROM table) AS nid) t2 ON t1.id &get; t2.nid LIMIT n;
两个表left join,一般不会被改写顺序,
而三个以上的left join他们之间也会自动选择顺序了
【SQL优化要点】
1、 消除type = ALL
2、 消除 using filesort
3、 消除 using temporary
4、 多表连接时,注意连接顺序是否我们提交的顺序,是否被改写了(有时候,被改写了反而更好,不一而论)
5、 注意 key_len 是否达到了预期,整个联合索引尽可能都被利用
【其他优化建议】
• 使用长连接避免连接开销。或者加大thread_cache_size,或者使用thread pool;
• 重要业务上线前,关键SQL必须逐个EXPLAIN分析,确保都有适当的索引;
• 请求频率很高的表上禁止运行长读写事务,避免发生严重锁等待等性能问题;
• 类似长URL(低于255长度)列检索,建议先进行HASH后创建索引,其检索效率会高很多倍;
• 区分冷热表,让热数据尽可能放在buffer中,提高读写效率;
• 如果需要经常统计结果,建议新增计数器,或者使用redis、mc来代替MySQL;
• 非精确性统计表总记录数时,可以执行SHOW TABLE STATUS查看估算结果;
• 所有列类型都设置默认值,严禁允许默认为NULL值的;
• 如果不能把多个大字段(长VARCHAR、TEXT、BLOB类型)分离到子表的话,就想办法合并成一个大字段,避免频繁的off-page;
• 个别时候可能需要采用冗余字段来存储,比如部分长度(尤其是取最右边的长度),或者反向存储,方便特殊的检索需求;
• 频繁读取的热数据,尽可能缓存在redis、mc中,哪怕只缓存10秒,如果每秒请求1000次的话,也可以减少1万次请求;
• 可以的话,采用多行记录同时INSERT,或者LOAD方式批量写入,提高写入效率,但也要避免锁时间太久的问题;
Index Condition Pushdown(ICP)
• 5.6以上,优化索引查询效率
• 以前:先检索全部记录,而后进行一次过滤
• 现在:边检索记录,边进行过滤
• 好处:降低SQL层得到的结果集,提高处理效率
• 优化支持range、ref、eq_ref、eq_or_null类型查询
• 查询优化器提示:Using index condition
• 在不支持ICP之前,MySQL进行索引查询时,会先根据索引查询记录,再根据WHERE条件来进行过滤。
• 在支持ICP后,MySQL在根据索引查找的同时,会根据WHERE条件对结果进行过滤,将WHERE条件的过滤操作放在存储引擎层,这样一来,
在一些查询中,ICP会大大提高上层SQL层(SERVER层)读取记录(fetch)效率,从而提高整体tps。
show global variables like 'optimizer_switch';
启用ICP:
set global optimizer_switch = "index_condition_pushdown=on";
关闭ICP:
set global optimizer_switch = "index_condition_pushdown=off";
新特性:MRR & BKA
MRR(Multi-Range Read)
• 5.6以上,减少磁盘随机访问,将随机访问转变成顺序访问,提高IO性能
• 适用于range、ref、eq_ref类型查询
• 数据访问较为顺序,查询辅助索引时,对查询结果先按照主键(ROWID)进行排序,并按照主键排序后的顺序,进行顺序查找
• 减少buffer pool中的页面被替换次数
• 批量处理对索引的查询操作
MRR工作方式:
• 将查询到的辅助索引键值放在一个缓冲中,这时缓冲中的数据是根据辅助所以进行排序的
• 将缓冲中的键值根据 ROWID进行排序
• 根据ROWID的排序顺序来访问实际的数据文件
新特性 BKA(Batched Key Access)
在MySQL 5.6中,BKA(Batched Key Access)联接算法可同时用于表连接以及join buffer时的索引访问。
BKA算法支持inner join、outer jon、semi-join,以及nested-outer join。BKA算法使得表扫描效率更高,以此实现JOIN优化。
此前BNL(Block Nested-Loop)联接算法只能用于inner join优化,现在也支持outer join、semi join、以及nested outer join等。
InnoDB引擎优化 - innodb buffer pool转储、预热
转储文件名为ib_buffer_pool, 转储的文件中只记录了space id和page no,所以非常小
InnoDB引擎优化 - read only transaction,只读事务
默认开启事务是READ WRITE,可以在开启事务时指定: START TRANSACTION READ ONLY;
如果以autocommit运行select,则视其为READ ONLY
只读事务不会为其创建事务,提高只读效率,只读事务减少了创建read view的开销,因为这是个全局锁竞争的热点。
InnoDB引擎优化 - 物化Innodb表的统计信息
控制选项:innodb_stats_persistent
当开启该选项后,就会将表的统计信息记录到ibdata中,只有手动执行ANALYZE TABLE才会对其进行更新。
在5.6中,引入的一个新参数innodb_stats_auto_recalc用于控制是否进行自动统计信息计算。当表上的记录修改超过1/16比例,或者总共超过20亿行时,
或者访问information_schema下的一些特定表,就会对统计信息重新计算;这只对在建表时打开了innodb_stats_persistent或者指定了建表选项STATS_PERSISTEND=1生效,
采样page的个数通过参数innodb_stats_persistent_sample_pages来控制(实际读取的page数会大于该值)。
information_schema.TABLES
information_schema.STATISTICS
information_schema.PARTITIONS
information_schema.KEY_COLUMN_USAGE
information_schema.TABLE_CONSTRAINTS
information_schema.REFERENTIAL_CONSTRAINTS
InnoDB引擎优化 - 引入独立page cleaner thread和purge thrad
启用独立的page cleaner线程和 purge thread,通过选项 innodb_puge_threads 来控制。在5.6版本下,还只能设置为1,从5.7开始,就可以设置成更大值
InnoDB引擎优化 - 死锁检测增强
启用 innodb_print_all_deadlocks 选项,即可将全部死锁信息打印输出到日志文件中,在以前,只能在show engine innnodb status中打印最后一次死锁信息
InnoDB引擎优化 - 独立undo表空间
innodb_undo_tablespaces #undo 表空间的个数,将所有的回滚段平分到这么多个ibd表空间文件中,这个值一旦设置,则不可更改。
配置这个及下面的选项,是为&get;了将undolog从Ibdata中独立出来,并且由于undo log是随机写,可以放到SSD盘上来提高性能
innodb_undo_directory #表示undo log表空间文件的路径,启动前设置
innodb_undo_logs #等同于老版本的innodb_rollback_segments,一个事务中最多可以多少个回滚段。
InnoDB引擎优化 - InnoDB page size增强
支持4K、8K格式,适用于绝大多数行平均大小较低值的场景。
从5.7开始,则新增支持32K、64K格式,以适应数据仓库中长日志格式场景。
InnoDB引擎优化 - page checksum增强
innodb_checksum = 0|1,是否校验innodb磁盘文件
innodb_checksum_algorithm #更快的checksum算法(crc32), innodb|crc32|none|strict_innodb|strict_crc32|strict_none
binlog_checksum = CRC32 | NONE,校验算法
master_verify_checksum = 0|1,读取binlog时,是否校验
slave_sql_verify_checksum = 0|1,在slave上读取relay log时,是否校验relay log
5.6新特性:EXPLAIN增强
支持DML的EXPLAIN,但是需要注意可能有不准确的情况。
EXPLAIN结果中,type列有时候会变成range,但实际上是use index的,和改成SELECT后的执行计划不一致。
而如果是多表的DML执行计划解析,则没有问题。
5.6新特性:查询优化器跟踪
启用了optimizer_trace功能,和oracle的执行计划类似,可以输出json格式结果,并且开始往CBO方向靠。
http://imysql.com/2014/08/05/a-fake-bug-with-eq-range-index-dive-limit.shtml
http://blog.163.com/li_hx/blog/static/18399141320147521735442/
show tables like ‘INNODB_SYS_%';
5.6新特性:复制增强
1、 开始支持GTID,极大方便了复制的便利性以及可靠性;
2、 支持多线程并发复制,不过只能是基于database级别的,意义不大,可以用percona或者mariadb分支特性;
3、 slave库延迟更新,防止误操作;
4、 binlog_row_image = full|minimal|noblob,减少binlog大小;同时binlog和relay log也支持crash safe了,上面checksum已介绍过;
5、 支持将master、slave、relay log info等信息记录在innodb表中,取代原先的写文件做法,提高可靠性;
6、 可以利用mysqlbinlog构建一个binlog server:--read-from-remote-server --raw
7、 binlog group commit
Tips:当引入binlog group commit后,sync_binlog的含义就变了,假定设为1000,表示的不是1000个事务后做一次fsync,而是1000个事务组。
5.7新特性:其他
innodb_purge_threads 可以设置大于1,有效的进行purge
InnoDB REDO log size up to 512 Gbyte (日志大小达到了512G,有效的提高了检查点的写入)
mysql选择,percona,mariadb
Percona分支特有选项/参数
enforce_storage_engine
expand_fast_index_creation
² 扩展快速创建索引特性,尽可能避免在一些场景下执行唯一约束、外键约束检查,提高性能
² mysqldump中新增选项 --innodb-optimize-keys,在备份文件最莫问再加上enable keys,以及唯一约束、外键约束检查等
extra_max_connections
extra_port
² thread pool功能的扩展,允许使用额外端口和线程作为管理员救命用
innodb_kill_idle_transaction
² 0(不启用)/N秒,干掉超过N秒的事务(不光是只读查询)
innodb_log_block_size
² 默认512字节,可以调整成4K,以适应SSD设备,提高IO性能
innodb_show_locks_held
² 在SHOW INNODB STATUS中显式多少个锁信息
innodb_show_verbose_locks
² 0/1,是否在SHOW INNODB STATUS中显式更多锁相关的信息
log_slow_filter
² slowlog过滤器,哪些类型的slowlog不记录
log_slow_rate_limit
² 1 ~ 1000,和log_slow_rate_type结合起来用。记录每 1/N次slowlog,不全记录
log_slow_rate_type
² slowlog控制范围是每个session,还是每个query。如果是每个session,需要注意连接池情况下无法生效,并且对复制线程也不生效
log_slow_sp_statements
² 是否记录存储过程产生的slowlog
log_slow_verbosity
² 设置slowlog中,哪些类型的信息要被记录下来,一般设置为full
max_binlog_files
² 至多保留多少个binlog文件
slow_query_log_timestamp_always
² 每次slowlog中,是否总是记录时间戳
thread_statistics
userstat
² 和thread_statistics一起,设置是否统计每个user和thread的信息,存储在information_schema的几个表中
CLIENT_STATISTICS
INDEX_STATISTICS
TABLE_STATISTICS
THREAD_STATISTICS
USER_STATISTICS
slow_query_log_timestamp_precision
slow_query_log_use_global_control
Innodb_deadlocks
Innodb_max_trx_id
Innodb_purge_trx_id
Innodb_s_lock_os_waits
Innodb_s_lock_spin_rounds
Innodb_s_lock_spin_waits
Innodb_x_lock_os_waits
Innodb_x_lock_spin_rounds
Innodb_x_lock_spin_waits
【重要】如果需要TokuDB,那么建议它和MariaDB组合使用