QSQL 是一个帮助你分析 mysql 查询语句并优化的小工具,原理是使用 explain 执行计划。
public class QSqlTest { private QSql qSql; @Before public void before(){ String url = "jdbc:mysql://127.0.0.1:3306/annal"; String user = "root"; String pass = "123456"; Config config = new Config(url, user, pass); qSql = new QSql(config); } private final String SQL1 = "select * from t_user where username in (select username from t_topic where stars > 0)"; @Test public void test1(){ qSql.analyze(SQL1); } }
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ QSQL v1.0 (by biezhi) │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Basic Infomation │ ├─────────────────────────────┬─────────────────────────────┬─────────────────────────────┬────────────────────────────┤ │ host │ user_name │ db_name │ db_version │ ├─────────────────────────────┼─────────────────────────────┼─────────────────────────────┼────────────────────────────┤ │ 127.0.0.1 │ root │ annal │ 5.7.15 │ └─────────────────────────────┴─────────────────────────────┴─────────────────────────────┴────────────────────────────┘ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ System Paramter │ ├───────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────┤ │ parameter │ value │ ├───────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────┤ │ binlog_cache_size │ 32768 │ │ bulk_insert_buffer_size │ 8388608 │ │ have_query_cache │ YES │ │ interactive_timeout │ 28800 │ │ join_buffer_size │ 262144 │ │ key_buffer_size │ 8388608 │ │ key_cache_age_threshold │ 300 │ │ key_cache_block_size │ 1024 │ │ key_cache_division_limit │ 100 │ │ large_pages │ OFF │ │ locked_in_memory │ OFF │ │ long_query_time │ 10.000000 │ │ max_allowed_packet │ 4194304 │ │ max_binlog_cache_size │ 18446744073709547520 │ │ max_binlog_size │ 1073741824 │ │ max_connections │ 151 │ │ max_connect_errors │ 100 │ │ max_join_size │ 18446744073709551615 │ │ max_length_for_sort_data │ 1024 │ │ max_seeks_for_key │ 18446744073709551615 │ │ max_sort_length │ 1024 │ │ max_tmp_tables │ 32 │ │ max_user_connections │ 0 │ │ optimizer_prune_level │ 1 │ │ optimizer_search_depth │ 62 │ │ query_cache_size │ 1048576 │ │ query_cache_type │ OFF │ │ query_prealloc_size │ 8192 │ │ range_alloc_block_size │ 4096 │ │ read_buffer_size │ 131072 │ │ read_rnd_buffer_size │ 262144 │ │ sort_buffer_size │ 262144 │ │ sql_mode │ ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,N │ │ │ O_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_US │ │ │ ER,NO_ENGINE_SUBSTITUTION │ │ thread_cache_size │ 9 │ │ tmp_table_size │ 16777216 │ │ wait_timeout │ 28800 │ └───────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Optimizer Switch │ ├───────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────┤ │ switch_name │ value │ ├───────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────┤ │ index_merge │ on │ │ index_merge_union │ on │ │ index_merge_sort_union │ on │ │ index_merge_intersection │ on │ │ engine_condition_pushdown │ on │ │ index_condition_pushdown │ on │ │ mrr │ on │ │ mrr_cost_based │ on │ │ block_nested_loop │ on │ │ batched_key_access │ off │ │ materialization │ on │ │ semijoin │ on │ │ loosescan │ on │ │ firstmatch │ on │ │ duplicateweedout │ on │ │ subquery_materialization_cost_based │ on │ │ use_index_extensions │ on │ │ condition_fanout_filter │ on │ │ derived_merge │ on │ └───────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────┘ >>>> original sql <<<< ------------------------------------------------------------------------------------------------------------------------ select * from t_user where username in ( select username from t_topic where stars > 0 ) ------------------------------------------------------------------------------------------------------------------------ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ explain report │ ├────────────────┬────────────────┬────────────────┬────────────────┬────────────────┬────────────────┬────────────────┬────────────────┬────────────────┬────────────────┬────────────────┬───────────────────────────────┤ │ id │ select_type │ table │ partitions │ type │ possible_keys │ key │ key_len │ ref │ rows │ filtered │ Extra │ ├────────────────┼────────────────┼────────────────┼────────────────┼────────────────┼────────────────┼────────────────┼────────────────┼────────────────┼────────────────┼────────────────┼───────────────────────────────┤ │ 1 │ SIMPLE │ t_user │ │ ALL │ PRIMARY │ │ │ │ 3 │ 100.0 │ │ │ 1 │ SIMPLE │ t_topic │ │ ALL │ │ │ │ │ 21 │ 4.76 │ Using where; │ │ │ │ │ │ │ │ │ │ │ │ │ FirstMatch(t_user); │ │ │ │ │ │ │ │ │ │ │ │ │ Using join buffer (Block │ │ │ │ │ │ │ │ │ │ │ │ │ Nested Loop) │ └────────────────┴────────────────┴────────────────┴────────────────┴────────────────┴────────────────┴────────────────┴────────────────┴────────────────┴────────────────┴────────────────┴───────────────────────────────┘ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ explain message report │ ├────────────────┬────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ level │ code │ message │ ├────────────────┼────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ Warning │ 1681 │ 'EXTENDED' is deprecated and will be removed in a future release. │ │ Note │ 1003 │ /* select#1 */ select `annal`.`t_user`.`username` AS `username`,`annal`.`t_user`.`password` AS `password`,`annal`.`t_user`.`nickname` AS `nickname`,`annal`.`t_user`.`email` │ │ │ │ AS `email`,`annal`.`t_user`.`avatar` AS `avatar`,`annal`.`t_user`.`signature` AS `signature`,`annal`.`t_user`.`followers` AS `followers`,`annal`.`t_user`.`following` AS │ │ │ │ `following`,`annal`.`t_user`.`topics` AS `topics`,`annal`.`t_user`.`privated` AS `privated`,`annal`.`t_user`.`state` AS `state`,`annal`.`t_user`.`created` AS │ │ │ │ `created`,`annal`.`t_user`.`logined` AS `logined` from `annal`.`t_user` semi join (`annal`.`t_topic`) where ((`annal`.`t_topic`.`stars` > 0) and │ │ │ │ (`annal`.`t_user`.`username` = `annal`.`t_topic`.`username`)) │ └────────────────┴────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ :: optimizer sql :: select `annal`.`t_user`.`username` AS `username`,`annal`.`t_user`.`password` AS `password`,`annal`.`t_user`.`nickname` AS `nickname`,`annal`.`t_user`.`email` AS `email`,`annal`.`t_user`.`avatar` AS `avatar`,`annal`.`t_user`.`signature` AS `signature`,`annal`.`t_user`.`followers` AS `followers`,`annal`.`t_user`.`following` AS `following`,`annal`.`t_user`.`topics` AS `topics`,`annal`.`t_user`.`privated` AS `privated`,`annal`.`t_user`.`state` AS `state`,`annal`.`t_user`.`created` AS `created`,`annal`.`t_user`.`logined` AS `logined` from `annal`.`t_user` semi join ( `annal`.`t_topic` ) where ( ( `annal`.`t_topic`.`stars` > 0 ) and ( `annal`.`t_user`.`username` = `annal`.`t_topic`.`username` ) ) analyze finished.
- id: SELECT 查询的标识符. 每个 SELECT 都会自动分配一个唯一的标识符.
- select_type: SELECT 查询的类型.
- table: 查询的是哪个表
- partitions: 匹配的分区
- type: join 类型
- possible_keys: 此次查询中可能选用的索引
- key: 此次查询中确切使用到的索引.
- ref: 哪个字段或常数与 key 一起被使用
- rows: 显示此查询一共扫描了多少行. 这个是一个估计值.
- filtered: 表示此查询条件所过滤的数据的百分比
- extra: 额外的信息
select_type 表示了查询的类型, 它的常用取值有:
SIMPLE, 表示此查询不包含UNION查询或子查询PRIMARY, 表示此查询是最外层的查询UNION, 表示此查询是UNION的第二或随后的查询DEPENDENT UNION,UNION中的第二个或后面的查询语句, 取决于外面的查询UNION RESULT,UNION的结果SUBQUERY, 子查询中的第一个SELECTDEPENDENT SUBQUERY: 子查询中的第一个SELECT, 取决于外面的查询. 即子查询依赖于外层查询的结果.