mysql高效查询_mysql 高效率查询背景

说起mysql查询效率问题,就无法绕开索引问题,而innodb索引是mysql存储引擎中的重中之重,innodb索引包括“主键索引(聚集索引)”也就是实际数据和主键数据存储在一起的索引。innodb除了主键索引以外就是二级索引,二级索引叶子结点的数据区存储的是主键,mysql每个数据页面有16k大小,innodb在执行插入数据后就已经根据唯一键将数据页排好顺序,索引结构暂时不做过多解释。

那我们新建二级索引的时可以根据“近1”原则创建,创建是参考sql语句:select  COUNT(DISTINCT(CONCAT(date,name)))/count(*) ;

例如,想要建立两个字段的联合索引,而第二个字段你可以选择使用前缀的创建方式,也就是第二个字段只使用部分数据。

比如查询优化中我们要遵循最佳做前缀原则,这个时候我们很可能想根据后缀去查询,我们可以将数据倒置后,存储冗余一列在按照左匹配模糊查询。

如网址列查询我们可以存储为:moc.udiab.www 这种形式。

按照创建索引涉及的列去重后的总数和数据总数做对比,结果越趋近于1,则索引查询效果越好。因为越趋近于0说明数据差距不大,所扫描的数据代价越高。

=========JOIN=========

先说下join吧,两个表的join操作,实质是将一张表的记录放入另一张表进行匹配过滤,mysql有join_buffer_size设置,这个设置会决定每次从驱动表中拿出多少条数据去另一张表做过滤,如果内存允许的话,尽量将其调大(默认256KB)这样会减少IO开销,每次拿驱动表中多的数据去和另一张表的数据作匹配,sql优化器会试图将两个表的操作先优化为内连接也就是inner join,这样做可以使用驱动表优化策略,会将小表设置为驱动表。

========子查询========

子查询的性能也是关键,子查询可以分为相关子查询和独立子查询;每种查询方式又分为标量子查询(返回单条记录)和结果集子查询。

(1)如:select * from td1 where name=(select a from td2 where td2.b=td1.c limit 1)  相关子查询中的标量子查询;

其实相关标量子查询,如果子查询内能够使用索引速度也是基本没什么问题的,因为它会在外层查询中先取出一条数据,然后去子查询中做唯一匹配,虽然稍复杂些,但是性能损耗可以接受

(2)如:select * from td1 where name in (select a from td2) 独立子查询;

ps:如果是上面这种则相对复杂了很多,如果子查询的返回结果数量没有超过mysql服务的预设值(tmp_table_size),则会以memory引擎创建一个td2 临时表并创建Hash索引,因为td1中是以等值方式去td2中匹配的;超过了就会创建磁盘物理表并建立B+Tree索引。

《2.1》针对于in子查询,查询优化器会将in优化为join,那么转换为join的情况则不同,独立子查询如果子查询返回数据库唯一键,则直接可转成join。

《2.2》如果子查询返回非唯一键,则会使用物化表(按照ps的规则),将结果集先去重,然后在进行join。

(3)如:select * from td1 where name in (select a from td2 where td1.a=td2.b) 相关子查询中使用了主键;

相关子查询去重后在进行semi join,使用以下命令选择开启:

semijoin={on|off}

materialization={on|off}

loosescan={on|off}

subquery_materialization_cost_based={on|off}

4种情况:

《3.1》如果子查询中select返回是数据库唯一键 ,情况也是直接转换为semi join。

《3.2》mysql会创建一个临时表,每次将主表数据取出后在子查询表中查找数据,查找到以后插入临时表,该临时表中不会有重复的数据,当数据插入完毕以后,在与临时表做semi join。

《3.3》使用FirstMatch方法在子查询表中返回一条语句后,即返回,不在向后继续寻找。

《3.4》使用LooseScan,依赖本身的索引,进行group by进行去重后,在semi join

==================

mysql查询部分包括,(1)sql执行器,(2)sql优化器。

sql优化的执行过程可以先开启sql优化日志后(SET optimizer_trace='enabled=on';),到information_schema.OPTIMIZER_TRACE这个表中进行优化过程的查询,结合查询计划就能够看到mysql究竟是怎样执行最终的sql的。

查询优化日志中,我们可以主要观察where条件优化,join优化,和analyzing_range_alternatives查询成本优化。

这里我们可以拿analysisi_query_cost查询成本优化为例,row查询默认开销因子为0.2,主键索引数据页查询因子为1,按照公式=主键索引数据页*1+行数*0.2,最终获得查询成本cost的值,优化器会根据cost值,取最小的执行查询。

{"steps": [

{"join_preparation": {"select#": 1,"steps": [

{"expanded_query": "/* select#1 */ select `t_day_stock`.`STOCK` AS `STOCK`,`t_day_stock`.`DATE` AS `DATE`,`t_day_stock`.`OPEN` AS `OPEN`,`t_day_stock`.`CLOSE` AS `CLOSE`,`t_day_stock`.`HIGH` AS `HIGH`,`t_day_stock`.`LOW` AS `LOW`,`t_day_stock`.`VOLUME` AS `VOLUME`,`t_day_stock`.`VALUE` AS `VALUE`,`t_day_stock`.`NUMBER_OF_TRADES` AS `NUMBER_OF_TRADES`,`t_day_stock`.`PRECLOSE` AS `PRECLOSE` from `t_day_stock` where ((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))"}

]

}

},

{"join_optimization": {"select#": 1,"steps": [

{"condition_processing": {"condition": "WHERE","original_condition": "((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))","steps": [

{"transformation": "equality_propagation","resulting_condition": "((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))"},

{"transformation": "constant_propagation","resulting_condition": "((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))"},

{"transformation": "trivial_condition_removal","resulting_condition": "((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))"}

]

}

},

{"table_dependencies": [

{"table": "`t_day_stock`","row_may_be_null": false,"map_bit": 0,"depends_on_map_bits": [

]

}

]

},

{"ref_optimizer_key_uses": [

{"table": "`t_day_stock`","field": "STOCK","equals": "'600228.SH'","null_rejecting": false},

{"table": "`t_day_stock`","field": "STOCK","equals": "'600228.SH'","null_rejecting": false},

{"table": "`t_day_stock`","field": "STOCK","equals": "'600228.SH'","null_rejecting": false}

]

},

{"rows_estimation": [

{"table": "`t_day_stock`","range_analysis": {"table_scan": {"rows": 425496,"cost": 98608},"potential_range_indices": [

{"index": "PRIMARY","usable": true,"key_parts": ["STOCK","DATE"]

},

{"index": "stock_date","usable": true,"key_parts": ["STOCK","DATE"]

},

{"index": "stock","usable": true,"key_parts": ["STOCK"]

},

{"index": "date","usable": true,"key_parts": ["DATE"]

}

],"setup_range_conditions": [

],"group_index_range": {"chosen": false,"cause": "not_group_by_or_distinct"},"analyzing_range_alternatives": {"range_scan_alternatives": [

{"index": "PRIMARY","ranges": ["600228.SH <= STOCK <= 600228.SH AND DATE < 2004-01-12 00:00:00"],"index_dives_for_eq_ranges": true,"rowid_ordered": false,"using_mrr": false,"index_only": false,"rows": 3,"cost": 4.61,"chosen": true},

{"index": "stock_date","ranges": ["600228.SH <= STOCK <= 600228.SH AND DATE < 2004-01-12 00:00:00"],"index_dives_for_eq_ranges": true,"rowid_ordered": false,"using_mrr": false,"index_only": false,"rows": 5,"cost": 7.01,"chosen": false,"cause": "cost"},

{"index": "stock","ranges": ["600228.SH <= STOCK <= 600228.SH"],"index_dives_for_eq_ranges": true,"rowid_ordered": true,"using_mrr": false,"index_only": false,"rows": 468,"cost": 562.61,"chosen": false,"cause": "cost"},

{"index": "date","ranges": ["DATE < 2004-01-12 00:00:00"],"index_dives_for_eq_ranges": true,"rowid_ordered": false,"using_mrr": false,"index_only": false,"rows": 7450,"cost": 8941,"chosen": false,"cause": "cost"}

],"analyzing_roworder_intersect": {"usable": false,"cause": "too_few_roworder_scans"}

},"chosen_range_access_summary": {"range_access_plan": {"type": "range_scan","index": "PRIMARY","rows": 3,"ranges": ["600228.SH <= STOCK <= 600228.SH AND DATE < 2004-01-12 00:00:00"]

},"rows_for_plan": 3,"cost_for_plan": 4.61,"chosen": true}

}

}

]

},

{"considered_execution_plans": [

{"plan_prefix": [

],"table": "`t_day_stock`","best_access_path": {"considered_access_paths": [

{"access_type": "ref","index": "PRIMARY","rows": 4254,"cost": 5105.8,"chosen": true},

{"access_type": "ref","index": "stock_date","rows": 310,"cost": 372,"chosen": true},

{"access_type": "ref","index": "stock","rows": 468,"cost": 561.6,"chosen": false},

{"access_type": "range","rows": 3,"cost": 5.21,"chosen": true}

]

},"cost_for_plan": 5.21,"rows_for_plan": 3,"chosen": true}

]

},

{"attaching_conditions_to_tables": {"original_condition": "((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))","attached_conditions_computation": [

],"attached_conditions_summary": [

{"table": "`t_day_stock`","attached": "((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))"}

]

}

},

{"refine_plan": [

{"table": "`t_day_stock`","pushed_index_condition": "((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))","table_condition_attached": null,"access_type": "range"}

]

}

]

}

},

{"join_explain": {"select#": 1,"steps": [

]

}

}

]

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值