postgresql是否对聚集索引进行O(1)查找?

时间:2016-02-06 21:04:32

标签: mysql sql postgresql indexing

问题如下:

  1. postgresql(或其他数据库实现)是否针对聚集索引进行O(1)查找? 即,从行的id(其中id列是聚集索引)直接查找文件系统上的行位置

  2. 如果无法进行此类查找,是否通过id log2n查找行?

  3. 考虑到这一点,postgresql或任何sql引擎是否有办法让索引产生位置到其他表中的行以避免这种情况?
  4. postgresql或任何sql引擎是否有办法直接查找行(以及与行如何移动相关的生命周期)? 我假设行不会相对于数据库引擎存储格式移动,除非聚集索引被更改...
  5. 这些问题源自实现多对多关系所需的以下联结表:

    junction_table:

    parent_id
    child_id
    

    检索一组child_ids

    select * from junction_table where parent_id=parent_value
    

    从根本上说,正确的实现应该为子行生成一组位置     更糟糕的是,至少有一种从child_ids集计算子行位置的方法

    VS一对多查询,它产生子行的方向位置:

    one_to_many_child_table:

    id
    name
    parent_id
    
    select * from child_table where p_id=parent_value
    

1 个答案:

答案 0 :(得分:1)

许多问题 - 让我提一下,把各个部分放在一起。

BTrees ,本质上是O(logn)。但是,你可以把它想象成O(1)。 BTree通常在每个节点中具有100个子链接。这表示一百万行只有3级深度;一个万亿行将大约6个级别。

此外,LRU缓存(例如MySQL在块级别执行)往往至少保留缓存中的非叶节点。 (在缓存中拥有所需的是大型数据库的真正的优化。)

B + Tree - 获取BTree并在叶节点之间添加双向链接。这使得“范围扫描”非常有效。

B + Tree索引是“最佳整体”。

群集在此上下文中,假设“群集”意味着唯一行标识符与数据一起存储。 (对于MySQL,这是PRIMARY KEY;其他一些我们是'rownum'。)

PRIMARY KEY 可以是群集和/或唯一的 - 这随数据库实施而变化。

辅助密钥通常是BTree,但从它到数据的方式是以不同的方式实现的。它可能直接指向数据;它可能有一个“rownum”,可用于查找记录;或者它可能有主键的副本,从而允许通过PK查找行。

MyISAM的InnoDB - PRIMARY KEY与数据集群,组织为B +树,并且是唯一的。这意味着PK的点查询将在BTree中进行一次潜水以找到整行。

InnoDB中的辅助密钥具有单独的BTree,并且在叶节点中找到PK的副本。因此,二级密钥查找是两次潜水(一次在BTree中,一次在PK +数据BTree中)。也就是说,除非索引是“覆盖”,并且在辅助键+主键中找到所需的所有列(对于SELECT)。

MySQL的MyISAM - MySQL的旧引擎(已经不再使用)将PRIMARY KEY和辅助密钥实现为BTree,其中叶节点具有到数据文件中的字节地址。因此,这两种类型的密钥都涉及一个BTree潜水加上文件系统“寻找”到另一个文件中。

哈希 - 真正的O(1)查找需要完美的哈希。没有人实现这一点。但是某些实现有一个Hash +某种形式的处理溢出。所以有时候是O(1),有时候慢一点。 (MySQL的MEMORY引擎上有Hash可用。)

Rownum / Rowid - 这是允许db直接进入行的某种数字。例如,Oracle使用这种东西。但是,您必须先将密钥映射到rownum。所以,这有点是一个两步的过程。 (MySQL不使用Rownum / Rowid。)

一对多 - 在任何情况下,使1:many高效的索引会使索引中的“many”聚集在一起,但可能会有“行” “他们指出分散在数据周围。

Postgresql (我不知道Postgres是如何工作的。)