mysql hint是什么意思

 我来答
爱可生云数据库
2020-06-03 · MySQL开源数据库领先者
爱可生云数据库
爱可生,金融级开源数据库和数据云服务整体解决方案提供商;优秀的开源数据库技术,企业级数据处理技术整体解决方案提供商;私有云数据库云服务市场整体解决方案提供商。
向TA提问
展开全部

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


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


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


比如表t1有100行记录,其中一列为f1。f1中唯一值的个数可以是100个,也可以是1个,当然也可以是1到100之间的任何一个数字。这里唯一值越的多少,就是这个列的可选择基数。


那看到这里我们就明白了,为什么要在基数高的字段上建立索引,而基数低的的字段建立索引反而没有全表扫描来的快。当然这个只是一方面,至于更深入的探讨就不在我这篇探讨的范围了。


概念二,关于HINT的使用。


这里我来说下HINT是什么,在什么时候用。


HINT简单来说就是在某些特定的场景下人工协助MySQL优化器的工作,使她生成最优的执行计划。一般来说,优化器的执行计划都是最优化的,不过在某些特定场景下,执行计划可能不是最优化。


比如:表t1经过大量的频繁更新操作,(UPDATE,DELETE,INSERT),cardinality已经很不准确了,这时候刚好执行了一条SQL,那么有可能这条SQL的执行计划就不是最优的。为什么说有可能呢?


来看下具体演示


譬如,以下两条SQL,

  • A:

  • select * from t1 where f1 = 20;

  • B:

  • select * from t1 where f1 = 30;

  • 如果f1的值刚好频繁更新的值为30,并且没有达到MySQL自动更新cardinality值的临界值或者说用户设置了手动更新又或者用户减少了sample page等等,那么对这两条语句来说,可能不准确的就是B了。

    这里顺带说下,MySQL提供了自动更新和手动更新表cardinality值的方法,因篇幅有限,需要的可以查阅手册。

    那回到正题上,MySQL 8.0 带来了几个HINT,我今天就举个index_merge的例子。

    示例表结构:

  • mysql> desc t1;+------------+--------------+------+-----+---------+----------------+| Field      | Type         | Null | Key | Default | Extra          |+------------+--------------+------+-----+---------+----------------+| id         | int(11)      | NO   | PRI | NULL    | auto_increment || rank1      | int(11)      | YES  | MUL | NULL    |                || rank2      | int(11)      | YES  | MUL | NULL    |                || log_time   | datetime     | YES  | MUL | NULL    |                || prefix_uid | varchar(100) | YES  |     | NULL    |                || desc1      | text         | YES  |     | NULL    |                || rank3      | int(11)      | YES  | MUL | NULL    |                |+------------+--------------+------+-----+---------+----------------+7 rows in set (0.00 sec)

  • 表记录数:

  • mysql> select count(*) from t1;+----------+| count(*) |+----------+|    32768 |+----------+1 row in set (0.01 sec)

  • 这里我们两条经典的SQL:

  • SQL C:

  • select * from t1 where rank1 = 1 or rank2 = 2 or rank3 = 2;

  • SQL D:

  • select * from t1 where rank1 =100  and rank2 =100  and rank3 =100;

  • 表t1实际上在rank1,rank2,rank3三列上分别有一个二级索引。

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

    显然,没有用到任何索引,扫描的行数为32034,cost为3243.65。

  • mysql> explain  format=json select * from t1  where rank1 =1 or rank2 = 2 or rank3 = 2\G*************************** 1. row ***************************EXPLAIN: {  "query_block": {    "select_id": 1,    "cost_info": {      "query_cost": "3243.65"    },    "table": {      "table_name": "t1",      "access_type": "ALL",      "possible_keys": [        "idx_rank1",        "idx_rank2",        "idx_rank3"      ],      "rows_examined_per_scan": 32034,      "rows_produced_per_join": 115,      "filtered": "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`.`t1`.`rank1` = 1) or (`ytt`.`t1`.`rank2` = 2) or (`ytt`.`t1`.`rank3` = 2))"    }  }}1 row in set, 1 warning (0.00 sec)

  • 我们加上hint给相同的查询,再次看看查询计划。

    这个时候用到了index_merge,union了三个列。扫描的行数为1103,cost为441.09,明显比之前的快了好几倍。

  • mysql> explain  format=json select /*+ index_merge(t1) */ * from t1  where rank1 =1 or rank2 = 2 or rank3 = 2\G*************************** 1. row ***************************EXPLAIN: {  "query_block": {    "select_id": 1,    "cost_info": {      "query_cost": "441.09"    },    "table": {      "table_name": "t1",      "access_type": "index_merge",      "possible_keys": [        "idx_rank1",        "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,      "filtered": "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`.`t1`.`rank1` = 1) or (`ytt`.`t1`.`rank2` = 2) or (`ytt`.`t1`.`rank3` = 2))"    }  }}1 row in set, 1 warning (0.00 sec)

  • 我们再看下SQL D的计划:

  • 不加HINT,

  • mysql> explain format=json select * from t1 where rank1 =100 and rank2 =100 and rank3 =100\G*************************** 1. row ***************************EXPLAIN: {  "query_block": {    "select_id": 1,    "cost_info": {      "query_cost": "534.34"    },    "table": {      "table_name": "t1",      "access_type": "ref",      "possible_keys": [        "idx_rank1",        "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,      "filtered": "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`.`t1`.`rank3` = 100) and (`ytt`.`t1`.`rank2` = 100))"    }  }}1 row in set, 1 warning (0.00 sec)

  • 加了HINT,

  • mysql> explain format=json select /*+ index_merge(t1)*/ * from t1 where rank1 =100 and rank2 =100 and rank3 =100\G*************************** 1. row ***************************EXPLAIN: {  "query_block": {    "select_id": 1,    "cost_info": {      "query_cost": "5.23"    },    "table": {      "table_name": "t1",      "access_type": "index_merge",      "possible_keys": [        "idx_rank1",        "idx_rank2",        "idx_rank3"      ],      "key": "intersect(idx_rank1,idx_rank2,idx_rank3)",      "key_length": "5,5,5",      "rows_examined_per_scan": 1,      "rows_produced_per_join": 1,      "filtered": "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`.`t1`.`rank3` = 100) and (`ytt`.`t1`.`rank2` = 100) and (`ytt`.`t1`.`rank1` = 100))"    }  }}1 row in set, 1 warning (0.00 sec)

  • 对比下以上两个,加了HINT的比不加HINT的cost小了100倍。

    总结下,就是说表的cardinality值影响这张的查询计划,如果这个值没有正常更新的话,就需要手工加HINT了。相信MySQL未来的版本会带来更多的HINT。

dxzdr413
推荐于2016-08-22 · TA获得超过2064个赞
知道大有可为答主
回答量:3994
采纳率:0%
帮助的人:1179万
展开全部
埃及狮身人面像酒店在古埃及神话中,狮身人面像就是一个兽形的身影,通常描绘成一个横卧或母狮狮子与人类的头,但偶尔有一只猎鹰,鹰,或羊的头上。这个数字有它在古王国的起源,并与太阳神赛克麦特,谁也就是法老的激烈的战争神和保护有关。她仍然是一个强有力的人物,埃及宗教在其整个历史上,甚至在阿玛纳时期。狮身人面像经常被描述为赛克麦特的孩子。 [澄清]使用其他动物之上母狮身体的头,随后他们在那里建立或者是在埃及神殿在当时著名的城市或地区的名义上的神。

狮身人面像一般的角色,分别为圣殿守护者,他们被安置在建筑结构协会,如皇家陵墓和宗教寺庙。后来,狮身人面像,或者非常类似的东西原来埃及的概念,是由于原件和概念相对于其他文化传统的演变的描述翻译

也许第一次狮身人面像,Hetepheres II从第四王朝 - 。开罗MuseumPerhaps第一狮身人面像1描绘了第四王朝持续了2723年至2563年卑诗省Hetepheres II。最大,最有名的是大狮身人面像的吉萨,选址在吉萨高原上的尼罗河和约旦河西岸面临的正东,也是从同一时期(29°58'31“N,31°08'15 “E)。虽然它的建造日期是不确定的,狮身人面像的头部,现在被认为是法老哈夫拉的。在卡纳克公羊为首的狮身人面像在卢克索约会到十八dynastyWhat名的建设者给这些雕像

大道不得而知。可能有被竖立一千年以后,在1400 BCE,由图特摩斯四世的碑文上的石碑在大狮身人面像网站列出的那个时期,Khepera的地方太阳神三方面的名字 - 再 - 。亚图姆列入这些数字在墓和庙复合物迅速成为传统,许多法老了他们的头上面刻的守护者雕像为他们的坟墓,以显示他们与强大的神,赛克麦特密切的关系。
- 其他著名的埃及狮身人面像包括一个带有法老哈特谢普苏特,用她的肖像刻在花岗岩,这是目前在艺术的纽约大都会博物馆和孟菲斯的狮身人面像雪花石膏,目前在位于头部露天博物馆,在该网站上。主题扩大到狮身人面像守护衬途径墓葬和庙宇以及作为楼梯顶上,以非常隆重复合航班的职位细节有很大的途径。九百用公羊的头,代表阿蒙,建于底比斯,在那里他的崇拜是最强的。
本回答被提问者和网友采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询
?>

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式