2010-10-30 137 views
7

我的问题是数据库如何存储数据以及它如何在内部执行查询。数据库如何在B-Tree/B + Tree内部存储数据

假设我们有以下在我们的表中的字段:

  1. ID
  2. 名称
  3. 年龄
  4. 重量
  5. 经理

,我们查询select * from Table1 where age>50 and weight<100

我只是好奇它如何执行内部查询。

在这个例子中,B-Tre/B + Tree的节点包含什么?

回答

6

您选择的示例是单个树无法完成这项工作的少数情况之一(两个独立的范围)。

然而,我的工作正在进行中电子书的第一章介绍了B树索引的内部运作:http://use-the-index-luke.com/anatomy/

编辑了解详情为什么两个指标可能是上面的例子有用。

上面的查询可以通过三种可能的索引配置来支持:

  1. AGE级联索引,然后WEIGHT(以该顺序)。
    如果查询会读取所有记录WHERE AGE > 50,然后按WEIGHT进行过滤。

  2. 连接索引WEIGHT然后AGE(其他顺序)。
    这种方式不同:读取所有记录WHERE WEIGHT < 100,然后通过AGE进行过滤。

什么是更有效率取决于您拥有的数据。如果有更少的记录AGE > 50WEIGHT < 100第一个会更有效率,否则第二个。但是,如果您使用不同的值查询,则图片可能会更改。

串联索引不能很好地支持查询的原因是每个索引顺序只在一个轴上。每个索引条目都在另一个之前或之后,但从不在其旁边。所有索引条目构建一个链。

具有两个独立范围查询的查询将需要两个轴,不像链,但更像是一个棋盘。一个轴为AGE另一个为WEIGHT。如果可以的话,你的查询只需要扫描棋盘的一个角落。

但是,b树只有一个坐标轴,因此您必须首先选择使用哪个标准。如果您选择AGE这意味着从AGE 50开始,整个链将被扫描直到结束。只有部分存储在链条边上的记录也有资格获得WEIGHT < 100,其他记录必须读取,但将被丢弃。

因此,一个长长的故事来解释为什么一棵树不能支持具有两个独立范围子句的查询。在另一方面,一个连结指数可以执行以下操作相当不错:

WHERE age = 50 AND weight < 100 
WHERE weight = 100 AND age > 50 
WHERE age > 50 AND age < 70; 

但是,如果有两个不等式运营商在两个不同列中使用的问题出现了。

那么,该怎么办?

第三种可能的方法是在两列上有两个独立的索引。这可以让你拥有尽可能多的坐标轴(只需创建更多的索引)。但是,有几个庞大的问题。首先,并非所有的数据库产品都支持这一点。只要它得到支持,这是一个相当广泛的操作。它通常用于扫描每个索引的方式,为每个结果构建一个位图索引。这些位图索引然后被加入以应用AND运算符。这就是大量的数据管理 - 如果每个条件对于自己的条件都不是非常有选择性的,那么只需付出努力,但是两者都是非常有选择性的。

请问我的建议?

如果您的查询在OLTP环境中运行:请使用一个连接索引。 两个独立的索引只是最后一招的选项。但是,如果您在OLAP环境中工作,则可能无论如何都需要位图索引。

PS: 索引AGE是在我的书(与解决方案)的exercise - 尤其是因为存储AGE是一种不好的做法,你应该存储诞生之日起代替。

+0

嗨,马库斯,我已经通过你的工作进行中的电子书的链接。你已经非常清楚地解释了这些事情,很好的工作。我知道索引是如何存储在内部的,但作为我原来的问题,我们是否需要两种索引来处理这种类型的范围查询? – ZeNo 2010-10-31 05:36:51

+0

嗨,我猜这个盒子对于我的回答来说太少了,所以我已经编辑了上面的'一点点'。 – 2010-10-31 06:47:29

+0

非常感谢Markus对这种简洁的解释。我现在觉得开明:) – ZeNo 2010-10-31 10:59:45