MySQL index-related knowledge and often interview questions

Common interview questions

  First, the introduction of common interview questions related index, let us learn more objective index-related content

    • Q: What are the most common database query optimization approach is slow?
      • Classmate A: indexed.
    • Q: Why are indexed to optimize slow queries?
      • Classmate A: ... I do not know
      • Students B: Because the index is actually an optimized data structure of the query, such as Mysql the index is B + tree implementation, while the B + tree is a data structure that can optimize query speed, you can use the index to quickly find the data, we are able to query optimization.
    • Q: Do you know what data structure can speed up the search? (Hear this question here feel pit ...)
      • Students B: hash table, perfectly balanced binary tree, B tree, B + tree and so on.
    • Q: Since these data structures can optimize the query speed, why choose to use that kind Mysql B + tree?
      • Students B: ... I do not know
    • Q: a titles table, the primary key empno, title, fromdate three fields. Then the following statement will use the index it?
      select * from employees.titles where emp_no=1
      select * from employees.titles where title='1'
      select * from employees.titles where emp_no='1'andtitle=1
      select * from employees.titles where title='1'andemp_no=1
    • Q: Why hash table, perfectly balanced binary tree, B tree, B + tree can optimize queries, like why only that Mysql B + tree? What are the characteristics of a hash table?
    • A: If there is such a table (table name: sanguo):                                                                                                                                                                        

    Now create a hash index for the name field, note field value corresponding to the array index is calculated random hashing algorithm, so the hash collision may occur. So for such an index structure, now to execute the following sql statement:
select * from sanguo where name='周瑜'

Can 'Zhou Yu' calculated by the hash algorithm directly out of an array index, then be removed directly from the data and the data to get the address corresponding to the line data latch, and then the line data query. So if we execute the following sql statement:

select * from sanguo where name>'周瑜'

It is powerless, because the characteristics of the hash table is the ability to quickly query accurate, but does not support range queries.

If it is completely balanced binary tree?

Above or below the table data representing a complete balanced binary tree (for simplicity, corresponding to the address data is not drawn in the figure.):

FIG Each node should actually has four parts:

  • The left pointer, refers to the left subtree
  • The key
  • Storing address data corresponding to the key
  • Right pointer, pointing to the right subtree

Also need to be reminded that there is a sequence of binary, simply means that "the left is less than the right" if we're lookin 'Zhou Yu', need to find twice (the first time Cao Cao, the second time Zhou Yu), Bihar to the Greek table once more. And because the perfectly balanced binary tree is ordered, it is also supported by the scope of the search.

 

If B trees?

Above or below the table data represented by the B-tree (for simplicity, corresponding to the address data is not drawn in the figure.):

 

The same elements can be found, the B-tree to represent than complete balanced binary tree "short" because a B-tree node can store a plurality of elements.

 

If B + trees?

Above or below the table data representing a B + tree (for simplicity, corresponding to the address data is not drawn in the figure.)

 We can find the same element, B + tree than the B-tree to represent the "fat" because of the redundant non-leaf node of a B + tree in the leaf nodes, and linked with pointers between the leaf nodes.

 

Then the B + tree in the end what advantage?

  这里我们用“反证法”,假如我们现在就用完全平衡二叉树作为索引的数据结构,我们来看一下有什么不妥的地方。实际上,索引也是很“大”的,因为索引也是存储元素的,我们的一个表的数据行数越多,那么对应的索引文件其实也是会很大的,实际上也是需要存储在磁盘中的,而不能全部都放在内存中,所以我们在考虑选用哪种数据结构时,我们可以换一个角度思考,哪个数据结构更适合从磁盘中读取数据,或者哪个数据结构能够提高磁盘的IO效率。回头看一下完全平衡二叉树,当我们需要查询“张飞”时,需要以下步骤:

  1. 从磁盘中取出“曹操”到内存,CPU从内存取出数据进行笔记,“张飞”<“曹操”,取左子树(产生了一次磁盘IO)
  2. 从磁盘中取出“周瑜”到内存,CPU从内存取出数据进行笔记,“张飞”>“周瑜”,取右子树(产生了一次磁盘IO)
  3. 从磁盘中取出“孙权”到内存,CPU从内存取出数据进行笔记,“张飞”>“孙权”,取右子树(产生了一次磁盘IO)
  4. 从磁盘中取出“黄忠”到内存,CPU从内存取出数据进行笔记,“张飞”=“张飞”,找到结果(产生了一次磁盘IO)

  同理,回头看一下B树,我们发现只发送三次磁盘IO就可以找到“张飞”了,这就是B树的优点:一个节点可以存储多个元素,相对于完全平衡二叉树所以整棵树的高度就降低了,磁盘IO效率提高了。

  而B+树是B树的升级版,只是把非叶子节点冗余一下,这么做的好处是为了提高范围查找的效率。

  到这里可以总结出来,Mysql选用B+树这种数据结构作为索引,可以提高查询索引时的磁盘IO效率,并且可以提高范围查询的效率,并且B+树里的元素也是有序的。

那么,一个B+树的节点中到底存多少个元素合适呢?

  其实也可以换个角度来思考B+树中一个节点到底多大合适?

  答案是:B+树中一个节点为一页或页的倍数最为合适。因为如果一个节点的大小小于1页,那么读取这个节点的时候其实也会读出1页,造成资源的浪费;如果一个节点的大小大于1页,比如1.2页,那么读取这个节点的时候会读出2页,也会造成资源的浪费;所以为了不造成浪费,所以最后把一个节点的大小控制在1页、2页、3页、4页等倍数页大小最为合适。

那么,Mysql中B+树的一个节点大小为多大呢?

  这个问题的答案是“1页”,这里说的“页”是Mysql自定义的单位(其实和操作系统类似),Mysql的Innodb引擎中一页的默认大小是16k(如果操作系统中一页大小是4k,那么Mysql中1页=操作系统中4页),可以使用命令SHOW GLOBALSTATUS like 'Innodbpagesize'; 查看。并且还可以告诉你的是,一个节点为1页就够了。

为什么一个节点为1页(16k)就够了?

  解决这个问题,我们先来看一下Mysql中利用B+树的具体实现。

  Mysql中MyISAM和innodb使用B+树

  通常我们认为B+树的非叶子节点不存储数据,只有叶子节点才存储数据;而B树的非叶子和叶子节点都会存储数据,会导致非叶子节点存储的索引值会更少,树的高度相对会比B+树高,平均的I/O效率会比较低,所以使用B+树作为索引的数据结构,再加上B+树的叶子节点之间会有指针相连,也方便进行范围查找。上图的data区域两个存储引擎会有不同。

 

 MyISAM中的B+树

  MYISAM中叶子节点的数据区域存储的是数据记录的地址,MyISAM存储引擎在使用索引查询数据时,会先根据索引查找到数据地址,再根据地址查询到具体的数据。并且主键索引和辅助索引没有太多区别。

 主键索引

 

 

辅助索引

  

 

 InnoDB中的B+树

   InnoDB中主键索引的叶子节点的数据区域存储的是数据记录,辅助索引存储的是主键值

主键索引

辅助索引

 

 Innodb中的主键索引和实际数据时绑定在一起的,也就是说Innodb的一个表一定要有主键索引,如果一个表没有手动建立主键索引,Innodb会查看有没有唯一索引,如果有则选用唯一索引作为主键索引,如果连唯一索引也没有,则会默认建立一个隐藏的主键索引(用户不可见)。另外,Innodb的主键索引要比MyISAM的主键索引查询效率要高(少一次磁盘IO),并且比辅助索引也要高很多。所以,我们在使用Innodb作为存储引擎时,我们最好:

  1. 手动建立主键索引
  2. 尽量利用主键索引查询

 

回到我们的问题:为什么一个节点为1页(16k)就够了?

  对着上面Mysql中Innodb中对B+树的实际应用(主要看主键索引),可以发现B+树中的一个节点存储的内容是:

  • § 非叶子节点:主键+指针
  • § 叶子节点:数据

 

  假设我们一行数据大小为1K,那么一页就能存16条数据,也就是一个叶子节点能存16条数据;再看非叶子节点,假设主键ID为bigint类型,那么长度为8B,指针大小在Innodb源码中为6B,一共就是14B,那么一页里就可以存储16K/14=1170个(主键+指针),那么一颗高度为2的B+树能存储的数据为:117016=18720条,一颗高度为3的B+树能存储的数据为:11701170*16=21902400(千万级条)。所以在InnoDB中B+树高度一般为1-3层,它就能满足千万级的数据存储。在查找数据时一次页的查找代表一次IO,所以通过主键索引查询通常只需要1-3次IO操作即可查找到数据。所以也就回答了我们的问题,1页=16k这么设置是比较合适的,是适用大多数的企业的,当然这个值是可以修改的,所以也能根据业务的时间情况进行调整。

 

最左前缀原则

  我们模拟数据建立一个联合索引 select *,concat(right(emp_no,1),"-",right(title,1),"-",right(from_date,2)) from employees.titles limit 10;

 

我们判断一个查询条件能不能用到索引,我们要分析这个查询条件能不能利用某个索引缩小查询范围

对于 select from employees.titles where emp_no=1是能用到索引的,因为它能利用上面的索引所有查询范围,首先和第一个节点“4-r-01”比较,1<4,所以可以直接确定结果在左子树,同理,依次按顺序进行比较,逐步可以缩小查询范围。对于select from employees.titles where title='1'是不能用到索引的,因为它不能用到上面的所以,和第一节点进行比较时,没有empno这个字段的值,不能确定到底该去左子树还是右子树继续进行查询。对于 select * from employees.titles where title='1' and emp_no=1是能用到索引,按照我们的上面的分析,先用title='1'这个条件和第一个节点进行比较,是没有结果的,但是mysql会对这个sql进行优化,优化之后会将empno=1这个条件放到第一位,从而可以利用索引。

Guess you like

Origin www.cnblogs.com/zhuminghui/p/10930389.html