面试经常会问:mysql数据库有哪些优化也可以提升mysql性能?

在开始演示之前,我们先介绍两个概念。

概念一,数据的可选基数,也就是常说的基数值。

在生成各种执行计划之前,查询优化器必须从统计信息中获取相关数据,从而估算出每个操作涉及的记录数,这个相关数据就是基数。简单来说就是每个字段中每个值的唯一值分布状态。

例如,表t1有100行记录,其中一行是f1。f1中唯一值的个数可以是100,1,当然也可以是1到100之间的任意数。这里唯一的值是该列的可选基数。

那么看到这一点,我们就能理解为什么需要在高基数的字段上建立索引,而低基数的没有全表扫描快。当然这只是一个方面,进一步的讨论不在我讨论的范围之内。

概念二,关于暗示的使用。

这里我就说说什么是暗示,什么时候用暗示。

HINT简单来说就是在一些特定场景下,手动辅助MySQL优化器,让她生成最优的执行计划。一般来说,优化器的执行计划是最优的,但是在某些特定的场景中,执行计划可能不是最优的。

比如表t1,经历了很多频繁的更新操作,(更新,删除,插入),基数已经很不准确了。此时,一条SQL刚刚被执行,因此这条SQL的执行计划可能不是最优的。为什么可能?

我们来看看具体的演示。

例如,下面两个SQL,

答:

select * from t1其中f 1 = 20;

乙:

select * from t1其中f 1 = 30;

如果f1的值只是频繁更新到30,并没有达到MySQL自动更新基数值的临界值,或者用户设置了手动更新,或者用户减少了样本页面等。,那么这两种说法可能都不准确。

顺便提一下,MySQL提供了自动更新和手动更新表的基数值的方法。由于篇幅有限,有需要可以参考手册。

回到正题,MySQL 8.0带来了几个提示,所以我今天举一个index_merge的例子。

样本表结构:

mysql & gtdesc t 1;+ - + - + - + - + - +|场?| Type | Null | Key | Default | Extra?|+-+--+-+-+| id | int(11)?|没有?| PRI | NULL | auto _ increment | | rank 1?| int(11)?|是吗?| MUL | NULL | || rank2?| int(11)?|是吗?| MUL | NULL | || log_time?|日期时间|是?| MUL | NULL | | | prefix _ uid | varchar(100)|是?| | NULL | || desc1?|文|是?| | NULL | || rank3?| int(11)?|是吗?| MUL | NULL | |+ - + - + - + - +集合中的7行(0.00秒)

表记录的数量:

mysql & gt从t1中选择count(*);+-+| count(*)|+-+| 32768 |+-+65438+集合中的0行(0.01秒)

这里我们有两个经典SQL:

SQL C:

select * from t1其中rank1 = 1或rank2 = 2或rank 3 = 2;

SQL D:

select * from t1其中rank1 =100?而rank2 =100?而rank 3 = 100;

表t1实际上有三个列的辅助索引:Rank1、Rank2和Rank3。

然后我们来看看SQL C的查询计划。

很明显,没有使用索引,扫描的行数是32034,开销是3243.65。

mysql & gt解释一下?format=json select * from t1?其中rank1 =1或rank2 = 2或rank 3 = 2 \ G * * * * * * * * * * * * * * * * * * * * * 1。行* * * * * * * * * * * * * * * * * * * * * * * * * * *解释:{?" query _ block ":{ " select _ id ":1," cost_info": {?" query_cost": "3243.65" }," table": {?" table_name": "t1 "," access_type": "ALL ",?" possible _ keys ":[" idx _ rank 1 "," idx_rank2 "," idx_rank3 "?], ?" rows_examined_per_scan": 32034,?" rows _ produced _ per _ join ":115,?「过滤」:「0.36」,?" cost _ info ":{ " read _ cost ":" 3232.07 "," eval_cost": "11.58 "," prefix_cost": "3243.65 "," data_read_per_join": "49K "?}, ?" used_columns": [ "id "," rank1 "," rank2 "," log_time "," prefix_uid "," desc1 "," rank3 "?], ?" attached _ condition ":"(` ytt `.` t 1 `.` rank 1 `= 1 ` .)or(` ytt `.` t 1 `.` rank 3 ` = 2))" }?}}集合中的1行,1警告(0.00秒)

让我们向同一个查询添加提示,并再次查看查询计划。

此时使用index_merge、union union,使用三列。扫描的行数是1103,花费是441.09,明显比以前快了好几倍。

mysql & gt解释一下?format = JSON select/*+index _ merge(t 1)*/* from t 1?其中rank1 =1或rank2 = 2或rank 3 = 2 \ G * * * * * * * * * * * * * * * * * * * * * 1。行* * * * * * * * * * * * * * * * * * * * * * * * * * *解释:{?" query _ block ":{ " select _ id ":1," cost_info": {?" query_cost": "441.09" }," table": {?" table_name": "t1 "," access_type": "index_merge "," possible _ keys ":[" idx _ rank 1 "," idx_rank2 "," idx_rank3 "?], ?" key": "union(idx_rank1,idx_rank2,idx_rank3)",?" key_length": "5,5,5 "," rows _ examined _ per _ scan ":1103,?" rows _ produced _ per _ join ":1103,?“已过滤”:“100.00”,?" cost _ info ":{ " read _ cost ":" 330.79 "," eval_cost": "110.30 "," prefix_cost": "441.09 "," data_read_per_join": "473K "?}, ?" used_columns": [ "id "," rank1 "," rank2 "," log_time "," prefix_uid "," desc1 "," rank3 "?], ?" attached _ condition ":"(` ytt `.` t 1 `.` rank 1 `= 1 ` .)or(` ytt `.` t 1 `.` rank 3 ` = 2))" }?}}集合中的1行,1警告(0.00秒)

让我们再来看看SQL D的计划:

没有提示,

mysql & gtexplain format = JSON select * from t 1其中rank1 =100,rank2 =100,rank 3 = 100 \ G * * * * * * * * * * * * * * * * * * * * * 1。行* * * * * * * * * * * * * * * * * * * * * * * * * * *解释:{?" query _ block ":{ " select _ id ":1," cost_info": {?" query_cost": "534.34" }," table": {?" table_name": "t1 "," access_type": "ref ",?" possible _ keys ":[" idx _ rank 1 "," idx_rank2 "," idx_rank3 "?], ?" key": "idx_rank1 ",?" used_key_parts": [ "rank1 "?], ?" key_length": "5 "," ref": [ "const "?], ?" rows_examined_per_scan": 555,?" rows_produced_per_join": 0,?“已过滤”:“0.07”,?" cost _ info ":{ " read _ cost ":" 478.84 "," eval_cost": "0.04 "," prefix_cost": "534.34 "," data_read_per_join": "176 "?}, ?" used_columns": [ "id "," rank1 "," rank2 "," log_time "," prefix_uid "," desc1 "," rank3 "?], ?" attached _ condition ":"(` ytt `.` t 1 `.` rank 3 ` = 100)和(` ytt `.` t 1 `.` rank 2 ` = 100))" }?}}集合中的1行,1警告(0.00秒)

有了提示,

mysql & gtexplain format = JSON select/*+index _ merge(t 1)*/* from t 1其中rank1 =100,rank2 =100,rank 3 = 100 \ G * * * * * * * * * * * * * * * * * * * * * * * * * 1。行* * * * * * * * * * * * * * * * * * * * * * * * * * *解释:{?" query _ block ":{ " select _ id ":1," cost_info": {?" query_cost": "5.23" }," table": {?" table_name": "t1 "," access_type": "index_merge "," possible _ keys ":[" idx _ rank 1 "," idx_rank2 "," idx_rank3 "?], ?" key ":" intersect(idx _ rank 1,idx_rank2,idx_rank3)",?" key_length": "5,5,5 "," rows _ examined _ per _ scan ":1,?" rows _ produced _ per _ join ":1,?“已过滤”:“100.00”,?" cost _ info ":{ " read _ cost ":" 5.13 "," eval_cost": "0.10 "," prefix_cost": "5.23 "," data_read_per_join": "440 "?}, ?" used_columns": [ "id "," rank1 "," rank2 "," log_time "," prefix_uid "," desc1 "," rank3 "?], ?" attached _ condition ":"(` ytt `.` t 1 `.` rank 3 ` = 100)and(` ytt `.` t 1 `.` rank 1 `= 100))" }?}}集合中的1行,1警告(0.00秒)

对比以上两者,有提示的代价比没有提示的小100倍。

总而言之,表的基数值影响这个查询计划。如果该值没有正常更新,则需要手动添加提示。相信未来的MySQL版本会带来更多的提示。