MySQL优化器 limit影响的case

测试的用例中,因为limit的大小不同,而产生了完全不同的执行计划:

1. 测试case:  

create table t1 (
  f1 int(11) not null,
  f2 int(11) not null,
  f3 int(11) not null,
  f4 tinyint(1) not null,
  primary key (f1),
  unique key (f2, f3),
  key (f4)
) engine=innodb;

insert into t1 values
(1,1,991,1), (2,1,992,1), (3,1,993,1), (4,1,994,1), (5,1,995,1),
(6,1,996,1), (7,1,997,1), (8,1,998,1), (10,1,999,1), (11,1,9910,1),
(16,1,9911,1), (17,1,9912,1), (18,1,9913,1), (19,1,9914,1), (20,1,9915,1),
(21,1,9916,1), (22,1,9917,1), (23,1,9918,1), (24,1,9919,1), (25,1,9920,1),
(26,1,9921,1), (27,1,9922,1);

2. 两个不同limit的sql生成的执行计划:

  

  

3. 分析过程:

  

step 1.  获取可用的key,并计算rows

    update_ref_and_keys

      get_quick_record_count

  结果: f2, f4可用, 其分配的quick_rows=[22, 22]

  

  从上面的cardinality来看,f2,f4的过滤性都是2, 这样扫描f2,需要11行,然后根据primary回聚簇表扫描,有需要11行,所有,使用f2, f4索引的扫描需要22行。

  

step2:穷举下执行计划,找到cost最低的

    best_access_path

      best_extension_by_limited_search

   结果: 全表扫描的代价比较低,records=17, cost=2, 所以最后join->best_position[0]记录的就是全表扫描的执行计划。

  

step3:limit的影响

      在make_join_select的过程,对于limit进行处理,理由是:如果有limit,并且比当前best_position的记录数小,我们尝试是否有可用的index,减少扫描代价

      所以,在limit=10的时候,进行test_quick_select查找,并使用f2的索引。而limit=20的查询,不满足条件,所以继续使用全表扫描。

    

相关注释和代码如下:      

/*
        We plan to scan all rows.
        Check again if we should use an index.
        We could have used an column from a previous table in
        the index if we are using limit and this is the first table
      */
      if ((cond &&
              !tab->keys.is_subset(tab->const_keys) && i > 0) ||
          (!tab->const_keys.is_clear_all() && i == join->const_tables &&
           join->unit->select_limit_cnt <
           join->best_positions[i].records_read &&
           !(join->select_options & OPTION_FOUND_ROWS)))

  

step4: order by的影响

      函数:test_if_skip_sort_order

      limit=10:ref_key=f2:   判断有一个primary key的index可以覆盖order by查询, 但走pk的代价高于ref_key=f2。

       limit=20:ref_key=0:     判断有一个primary key的index可以覆盖order by查询,而且当前使用的是全表扫描,代价小于全表,所以选择pk。

所以,两个limit值不同的查询,导致了不同的执行计划。

MySQL优化器 limit影响的case

时间: 2024-08-29 02:11:16

MySQL优化器 limit影响的case的相关文章

数据库 mysql 优化器原理

MySQL查询优化器有几个目标,但是其中最主要的目标是尽可能地使用索引,并且使用最严格的索引来消除尽可能多的数据行. 你的最终目标是提交SELECT语句查找数据行,而不是排除数据行.优化器试图排除数据行的原因在于它排除数据行的速度越快,那么找到与条件匹配的数据行也就越快. 如何 更好的 利用索引: 1:尽量比较数据类型相同的数据列.当你在比较操作中使用索引数据列的时候,请使用数据类型相同的列.相同的数据类型比不同类型的性能要高一些. 例如,INT与BIGINT是不同的.CHAR(10)被认为是C

MySQL优化器功能开关optimizer_switch

MySQL 8.0新增特性 use_invisible_indexes:是否使用不可见索引,MySQL 8.0新增可以创建invisible索引,这一开关控制优化器是否使用invisible索引,on表示考虑使用. MySQL 5.7新增 derived_merge:派生表合并,类似Oracle的视图合并,当派生SQL中存在以下操作是无法展开UNION .GROUP .DISTINCT.LIMIT及聚合操作 duplicateweedout:是否使用使用临时表对semi-join产生的结果集去重

MySQL优化器不使用索引的情况

优化器选择不适用索引的情况 有时候,有乎其并没有选择索引而去查找数据,而是通过扫描聚集索引,也就是直接进行全表的扫描来得到数据.这种情况多发生于范围查找.JOIN链接操作等情况.例如 SELECT * FROM orderdetails WHERE orderid>10000 and orderid<102000; 通过SHOW INDEX FROM orderdetails可以看到 可以看到orderdetails有(orderID,ProductID)的联合主键.此外还有对于列OrderI

MySQL优化之—limit

问题描述:通常情况下MySQL数据库表查询通过limit关键字进行分页,当数据量不多时,能够非常快速返回数据据,但当数据达到百万级别是,当前页数字越大响应时间越长. 举个例子:用户表 200w 数据  select * from t_user limit 0,20 这是没有问题的,数据很快返回 select * from t_user limit 1000080,20 上面这条语句返回比较慢. 原因:limit 0,20 仅扫描了20条数据,就返回结果,而 limit 1000080,20 扫描

MySQL优化器join顺序

前一篇介绍了cost的计算方法,下面测试一下两表关联的查询: 测试用例 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 CREATE TABLE `xpchild` (   `id` int(11) NOT NULL,   `name` varchar(100) DEFAULT NULL,   `c1` int(11) DEFAULT NULL,   `c2` int(11) DEFAULT NULL,   PRIMARY KEY (`id`),   KEY `xpc

【MySQL】MySQL/MariaDB的优化器对in子查询的处理

参考:http://codingstandards.iteye.com/blog/1344833 上面参考文章中<高性能MySQL>第四章第四节在第三版中我对应章节是第六章第五节 最近分析生产环境慢查询,发现上线很久但是效率不高的查询 MySQL版本5.5.18 SELECT loc.cell_no AS m_cellNo ... FROM bs_loc loc LEFT JOIN st_stock_m m ON loc.cell_no = m.cell_no WHERE loc.zone_n

单表60亿记录等大数据场景的MySQL优化和运维之道

此文是根据杨尚刚在[QCON高可用架构群]中,针对MySQL在单表海量记录等场景下,业界广泛关注的MySQL问题的经验分享整理而成,转发请注明出处. 杨尚刚,美图公司数据库高级DBA,负责美图后端数据存储平台建设和架构设计.前新浪高级数据库工程师,负责新浪微博核心数据库架构改造优化,以及数据库相关的服务器存储选型设计. 前言 MySQL数据库大家应该都很熟悉,而且随着前几年的阿里的去IOE,MySQL逐渐引起更多人的重视. MySQL历史 1979年,Monty Widenius写了最初的版本,

单表60亿记录等大数据场景的MySQL优化和运维之道 | 高可用架构(转)

转自http://www.php1.cn/Content/DanBiao_60_YiJiLuDengDaShuJuChangJingDe_MySQL_YouHuaHeYunWeiZhiDao_%7C_GaoKeYongJiaGou.html, 更多详细资料请参看原文 此文是根据杨尚刚在[QCON高可用架构群]中,针对MySQL在单表海量记录等场景下,业界广泛关注的MySQL问题的经验分享整理而成,转发请注明出处. 杨尚刚,美图公司数据库高级DBA,负责美图后端数据存储平台建设和架构设计.前新浪高

[转载] 单表60亿记录等大数据场景的MySQL优化和运维之道 | 高可用架构

原文: http://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=209406532&idx=1&sn=2e9b0cc02bdd4a02f7fd81fb2a7d78e3&scene=1&key=0acd51d81cb052bce4ec2a825666e97fe7d6e1072fb7d813361771645e9403309eb1af025691162c663b60ea990c3781&ascene=0&