9

MySQL数据库InnoDB存储引擎查询优化器实现的分析之单表查询

 3 years ago
source link: https://blogread.cn/it/article/4768?f=hot1
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1       单表查询

1.1     单表range查询

1)       select * from nkeys where c3 > 3;    不能进行索引覆盖扫描         index range scan
2)       select c3 from nkeys where c3 > 3; 可以进行索引覆盖扫描         index only range scan

调用流程:

msyql_select -> JOIN::optimize -> make_join_statistics ->get_quick_record_count -> SQL_SELECT::test_quick_select->ha_innobase::scan_time ->get_key_scans_params ->check_quick_select->Opt_range.cc::check_quick_keys ->ha_innobase::records_in_range-> get_index_only_read_time -> ha_innobase::read_time ->get_best_ror_intersect ->get_best_covering_ror_intersect ->

a)         ha_innobase::scan_time函数,给出全表扫描read_time

i.              scan_time = (double) records / TIME_FOR_COMPARE + 1;

  1. mysql层面,返回一个record需要的时间(CPU时间)
  2. TIME_FOR_COMPARE = 5

ii.              return (double) (prebuilt->table->stat_clustered_index_size(聚簇索引叶页面数);

  1. innodb层面,全表扫描时间,用读取的page数计算(IO时间)
  2. 由于innodb是索引组织表,用不到page的预读,因此一次读取一个page

                      iii.              table_read_time = ha_innobase::scan_time() + scan_time + 1;

  1. 全表扫描总时间 = innodb读取数据块时间 + mysql比较记录时间 + 1
  2. 测试中:table_read_time = 4.3000000000000007

b)         check_quick_select函数,判断索引扫描的代价

c)         ha_innobase::records_in_range函数,判断给定range的索引扫描,将返回多少记录

i.              给定range的min_key,max_key,根据min_key,max_key构造查询条件,分别进行btr_cur_search_to_nth_level

ii.              传入的level是0,search到叶页面

iii.              根据返回的两个页面的关系,计算range中的数据量

iv.              详细的records_in_range函数实现,请见1.1.1章节

d)         get_index_only_read_time函数,当前scan为index only scan,调用此函数计算read_time

i.              cpu_cost = (double) found_records / TIME_FOR_COMPARE;


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK