- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章浅析MysQL B-Tree 索引由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
B-Tree 索引 。
不同的存储引擎也可能使用不同的存储结构,i如,NDB集群存储引擎内部实现使用了T-Tree结构存储这种索引,即使其名字是BTREE;InnoDB使用的是B+Tree.
B-Tree通常一位这所有的值都是按顺序存储的,并且每一个叶子页道根的距离相同。下图大致反应了InnoDB索引是如何工作的.
为什么mysql索引要使用B+树,而不是B树,红黑树 。
看完上面的文章就可以理解为何B-Tree索引能够快速访问数据了。因为存储引擎不再需要进行全表扫描获取需要的数据,叶子节点包含了所有元素信息,每一个叶子节点指针都指向下一个节点,所以很适合查找范围数据.
索引对多个值进行排列的依据是CREATE TABLE 语句中定义索引时的顺序.
那么,索引排序的规则就是按照 last_name ,first_name ,dob 的顺序来的.
可以使用 B-Tree 索引的查询类型 B-Tree索引适用于全键值、键值范围或键前缀查找。 键前缀查找只是用于根据最左前缀查找.
举个粒子:
1
2
3
4
5
6
7
|
CREATE
TABLE
People (
last_name
VARCHAR
( 50 )
NOT
NULL
,
first_name
VARCHAR
( 50 )
NOT
NULL
,
dob
date
NOT
NULL
,
gender enum (
'm'
,
'f'
)
NOT
NULL
,
KEY
( last_name, first_name, dob )
);
|
这个表的索引如下:
type结果 。
type结果值从好到坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL 。
一般来说,得保证查询至少达到range级别,最好能达到ref,否则就可能会出现性能问题.
possible_keys:sql所用到的索引 。
key:显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL 。
(1)全值匹配 全值匹配指的是和索引中的所有列进行匹配.
例如上面的People表的索引(last_name,first_name,dob)可以用于查找last_name='Cuba Allen',first_name='Chuang',dob='1996-01-01'的人。这就是使用了索引中的所有列进行匹配,即全值匹配.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
mysql> EXPLAIN
select
*
from
People
where
last_name =
'aaa'
and
first_name =
'bbb'
and
dob=
'2020-11-20'
\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table
: People
partitions:
NULL
type: ref
possible_keys: last_name
key
: last_name <
-----可以看到这个key就是我们定义的索引
key_len: 307
ref: const,const,const
rows
: 1
filtered: 100.00
Extra:
NULL
1 row
in
set
, 1 warning (0.00 sec)
ERROR:
No
query specified
|
(2)匹配最左前缀 可以只使用索引的第一个列进行匹配.
例如可以用于查找last_name='aaa'的人,即用于查找姓为Zeng的人,这里只使用了索引的最左列进行匹配,即匹配最左前缀.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
mysql> EXPLAIN
select
*
from
People
where
last_name =
'aaa'
\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table
: People
partitions:
NULL
type: ref
possible_keys: last_name
key
: last_name <
----使用了索引
key_len: 152
ref: const
rows
: 3
filtered: 100.00
Extra:
NULL
1 row
in
set
, 1 warning (0.00 sec)
ERROR:
No
query specified
|
(3)匹配列前缀 可以只匹配某一列的值的开头部分.
例如可以用于查找last_name LIKE ‘a%'的人,即用于查找所有以Z开头的姓的人,这里只使用了索引最左列的前缀进行匹配,即匹配列前缀.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
mysql> EXPLAIN
select
*
from
People
where
last_name =
'a%'
\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table
: People
partitions:
NULL
type: ref
possible_keys: last_name
key
: last_name <
---使用了索引
key_len: 152
ref: const
rows
: 1
filtered: 100.00
Extra:
NULL
1 row
in
set
, 1 warning (0.00 sec)
ERROR:
No
query specified
|
(4)匹配范围值 可以只适用索引的第一列查找符合某个范围内的数据.
例如可以用于查找last_name BETWEEN ‘aaa' AND ‘aaabbbccc'的人,即用于查找姓在aaa和aaabbbccc之间的人,这里只使用了索引最左列的前缀进行范围匹配,即匹配范围值.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
mysql> EXPLAIN
select
*
from
People
where
last_name
BETWEEN
'aaa'
and
'aaabbbccc'
\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table
: People
partitions:
NULL
type: range
possible_keys: last_name
key
: last_name <
---使用了索引
key_len: 152
ref:
NULL
rows
: 3
filtered: 100.00
Extra: Using
index
condition
1 row
in
set
, 1 warning (0.00 sec)
ERROR:
No
query specified
|
(5)精确匹配某一列并范围匹配另外一列 可以使第一列全匹配,第二列范围匹配.
例如可以用于查找last_name='aaa' AND first_name LIKE 'b%'的人,即用于查找姓是Zeng,名字以C开头的人,这里使用了索引的最左列精确匹配,第二列进行范围匹配.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
mysql> EXPLAIN
select
*
from
People
where
last_name =
'aaa'
and
first_name
like
'b%'
\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table
: People
partitions:
NULL
type: range
possible_keys: last_name
key
: last_name <
---使用了索引
key_len: 304
ref:
NULL
rows
: 1
filtered: 100.00
Extra: Using
index
condition
1 row
in
set
, 1 warning (0.00 sec)
ERROR:
No
query specified
|
(6)只访问索引的查询 查询只需访问索引,而无须访问数据行.
例如select last_name, first_name where last_name='aaa'; 这里只查询索引所包含的last_name和first_name列,则无须读取数据行.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
mysql> explain
select
last_name,first_name,dob
from
People
where
last_name =
'aaa'
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table
: People
partitions:
NULL
type: ref
possible_keys: last_name
key
: last_name
key_len: 152
ref: const
rows
: 1
filtered: 100.00
Extra: Using
index
1 row
in
set
, 1 warning (0.00 sec)
ERROR:
No
query specified
|
B-Tree 的限制 。
(1)只能按照索引的最左列开始查找。 例如People表中的索引无法用于查找first_name为'bbb'的人,也无法查找某个特定生日的人,因为这两个列都不是最左数据列.
(2)只能按照索引最左列的最左前缀进行匹配。 例如People表中的索引无法查找last_name LIKE ‘%b'的人,虽然last_name就是此索引的最左列,但MySQL索引无法查找以‘b'结尾的last_name的记录.
(3)只能按照索引定义的顺序从左到右进行匹配,不能跳过索引中的列。 例如People表中的索引无法用于查找last_name='a' AND bod='1996-01-01'的人,因为MySQL无法跳过索引中的某一列而使用索引中最左列和排在末尾的列进行组合。如果不指定索引中中间的列,则MySQL只能使用索引的最左列,即第一列.
(4)如果查询中有某个列的范围查询,则其右边所有列都无法使用索引优化查找。 例如有这样一个查询:where last_name='a' AND first_name LIKE 'b%' AND dob='1996-01-01'; 这个查询只能使用索引的前两列,因为这里LIKE是一个范围条件,则first_name后面的索引列都将失效。(优化点:尽量不要在索引列中使用LIKE等范围条件,改用多个等于条件来替代,保证后面的索引列能生效。) 。
以上就是浅析MysQL B-Tree 索引的详细内容,更多关于MysQL B-Tree 索引的资料请关注我其它相关文章! 。
原文链接:https://segmentfault.com/a/1190000038243722?utm_source=tuicool&utm_medium=referral 。
最后此篇关于浅析MysQL B-Tree 索引的文章就讲到这里了,如果你想了解更多关于浅析MysQL B-Tree 索引的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我有两种结构,Header 和Session,它们都符合协议(protocol)TimelineItem。 我有一个 Array 由 TimelineItem 组成,如下所示: [Header1, S
这个问题在这里已经有了答案: Multiple assignment and evaluation order in Python (11 个答案) 关闭 6 年前。 我刚接触python所以想问你
我试图找到一种方法来在 R 中获取 A、A、A、A、B、B、B、B、B 的所有可能的唯一排列的列表。 组合最初被认为是获得解决方案的方法,因此组合的答案。 最佳答案 我认为这就是你所追求的。 @bil
我怎样才能将两个给定的向量混合成一个新的向量,它以交替的顺序保存它们的值。 (f [a a] [b b]) ; > [a b a b] 这是我想到的: (flatten (map vector [:a
这是我的第一个问题,我开始学习Python。之间有区别吗: a, b = b, a + b 和 a = b b = a + b 当您在下面的示例中编写它时,它会显示不同的结果。 def fib(n):
这个问题在这里已经有了答案: Why is there an injected class name? (1 个回答) 12 个月前关闭。 我不知道如何解释: namespace A { struct
我尝试了一些代码来交换 Java 中的两个整数,而不使用第三个变量,使用 XOR。 这是我尝试过的两个交换函数: package lang.numeric; public class SwapVars
假设类 B 扩展类 A,并且我想为 B 声明一个变量。什么更有效?为什么? B b或 A b . 最佳答案 您混淆了两个不同的概念。 class B extends A { } 意味着B 是 A .
我不确定这个问题的标题是什么,这也可能是一个重复的问题。所以请相应地指导。 我是 python 编程的新手。我有这个简单的代码来生成斐波那契数列。 1: def fibo(n): 2: a =
我在谷歌上搜索了有关 dynamic_cast 的内容,我发现显式地将基类对象转换为派生类指针可能是不安全的。但是当我运行一些示例代码来检查它时,我没有收到任何错误。请在下面找到我的代码: class
这个问题在这里已经有了答案: What is this weird colon-member (" : ") syntax in the constructor? (14 个答案) 关闭 8 年前。
在不重现产生非整数值的表达式的情况下实现以下目标的惯用方法是什么(在我的真实情况下,该值是在我不想重现的冗长查询之后计算为百分比的): SELECT * FROM SomeTable WHERE 1/
在析构中,这两个代码的结果确实不同。我不确定为什么。 提示说 const [b,a] = [a,b] 将导致 a,b 的值为 undefined (从左到右的简单分配规则)。我不明白为什么会这样。 l
C++ Templates - The Complete Guide, 2nd Edition介绍max模板: template T max (T a, T b) { // if b < a th
我最近开始学习代码(Java),并根据第 15.17.3 节在 Oracle 网站上查找了模运算符。以下链接: http://docs.oracle.com/javase/specs/jls/se8/
无法理解以下行为。 d1 := &data{1}; 的区别d1 和 d2 := 数据{1}; &d1。两者都是指针,对吧?但他们的行为不同。这里发生了什么 package main import "f
这个问题在这里已经有了答案: How to make loop infinite with "x = y && x != y"? (4 个回答) How can i define variables
在我的程序中,当我调试我的代码时,它似乎在我生成的代码中的某处 X1=['[a,a,a]','[b,b,b]'] 还有我生成的其他地方 X2=[[a,a,a],[b,b,b]] 当我想添加这两个列表然
我试图使用递归将两个整数相乘,并意外编写了这段代码: //the original version int multiply(int a, int b) { if ( !b ) retu
我有一个列表中数字之间所有可能的操作组合: list = ['2','7','8'] 7+8*2 8+7*2 2*8+7 2+8*7 2-8*7 8-2/7 etc 我想知道是否可以说像 ('7*2+
我是一名优秀的程序员,十分优秀!