再谈搜索,索引等问题

索引的本质是关联、link,key -> 记录地址( row locator等)或者字段 -> 主Id 的一个映射

正排索引:id -> (col1, col2, col3), docId - > { wordId }

倒排索引:col -> id, wordId -> docId

为什么需要倒排索引?关系是这样的:

用col 通过倒排索引得到Id, 进而用Id通过正排得到整体,也就是得到了其他col

通过对象访问字段的时候 (obj.field, obj.getXXX() )就是查找正排,正排的结构就是字段按固定的顺序连续的聚合在一起

通过字段值找对象(或者通过word找doc)的时候就是查找倒排,一般说的索引都是倒排。


基本文件:顺序文件,散列文件

顺序文件

按是否按主键排序分为:排序顺序文件,一般顺序文件

按是逻辑顺序和物理顺序的映射方式分为:连续顺序文件和链接顺序文件


索引:索引对应的基本文件一般是顺序文件,散列文件自身支持快速查找。

稠密索引:每个记录对应一个索引项

稀疏索引:文件分块,索引项对应一个块

多级索引:索引的索引。对索引本身分块,每一块对应上层索引的一个索引项。越到上面,节点内key的gap越大


B树是2-3树(2-3树就是3阶B树)和二叉排序树的一般情况,所有的结点(内部、叶子)都可以存放数据,是基本文件本身按key以多叉树的形式组织存储,以支持快速查找,而不是基本文件 + 索引的模式

B+树 就是一个典型的多级索引,内部节点上key的的指针指向以该key起点的索引块,叶节点上的key的指针才指向基本文件中记录的位置。所有叶节点构成了基本文件的一个稠密索引。


支持搜索的系统,一般的情况内存是放不下所有的数据的,有两个方向:

1)垂直and/or水平partition数据,对应不同server,每个server是全load到内存,使用内存数据结构支持查找(hashmap, 红黑树,skip list等)

2)允许磁盘访问,用类似B树、B+树的磁盘数据结构支持查找


建索引的system model

读入一个Iterable<T>对象流,对于每个对象,根据配置添加 col -> object id的 索引项,就这么简单。


点查询:key是一个值。非unique index 上 多个结果那种也属于点查询 wordId -> {doc1, doc2 ... }

线查询:一维查询,范围查询,key满足一个连续范围。只有聚集索引支持高效的range查询,普通索引的rangge查询只是查找索引时候是连续的,最终取数据时候还是点查询


单个条件:只有一个条件ian

多维查询:高效的多维查询时用R-Tree,KD Tree这样的数据结构实现的,普通的多维查询,是选择一个selectivity最好的条件做查询,然后用其他条件过滤

1)search with the most selective index and  filter the result with the rest columns

2)  search with each index with each column and do intersect.

actual behavior is based on the server's knowledge of the data and index,甚至可能select列上有索引,但是执行计划确不用索引。


关于复合索引key(key1, key2, key2)

也没什么神秘的,就是把key1, key2, key3 复合成一个对象, 然后就是一个comparator问题, 比较复合key的时候,先比较key1, 相等再看key2

class CompoundKey implements Comparable<CompoundKey> {
	private int key1, key2, key3;
	public CompoundKey(int key1, int key2, int key3) {
		//...
	}
	@Override
	public int compareTo(CompoundKey o) {
		if (this.key1 > o.key1) return 1;
		if (this.key1 < o.key1) return -1;
		if (this.key2 > o.key2) return 1;
		if (this.key2 < o.key2) return -1;
		if (this.key3 > o.key3)return 1;
		if (this.key3 < o.key3)return -1;
		return 0;
	}
}

key (key1, key2, key3)的索引 可以被 key1, (key1, key2),(key1, key2, key3) 用,也就是,要想使用复合索引,Where中包含了key2,就必须有key1;包含了key3就必须有key1, key2。必须有前导列。

更正:对于建在(key1, key2)上的索引,只用key1搜索,由点查询变成一个range查询 : (key1, key2_min) -  (key1, key2_max)




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值