zoukankan      html  css  js  c++  java
  • PostgreSQL中的索引(二)

    在第一篇文章中,我们已经提到访问方法必须提供有关自身的信息。让我们看一下访问方法接口的结构。

    属性

    访问方法的所有属性都存储在«pg_am»表中(“am”代表访问方法)。我们还可以从同一个表中获取可用方法的列表:

    postgres=# select * from pg_am;
     amname |  amhandler  | amtype 
    --------+-------------+--------
     btree  | bthandler   | i
     hash   | hashhandler | i
     gist   | gisthandler | i
     gin    | ginhandler  | i
     spgist | spghandler  | i
     brin   | brinhandler | i
    (6 rows)
    
    postgres=# 
    

    虽然顺序扫描可以正确地引用访问方法,但由于历史原因,它不在此列表中。

    在PostgreSQL 9.5及更低版本中,每个属性都用«pg_am»表的单独字段表示。从版本9.6开始,使用特殊函数查询属性,并将其分为多个层:
    ·访问方法属性 - «pg_indexam_has_property»
    ·特定索引的属性 - «pg_index_has_property»
    ·索引的各列的属性 - «pg_index_column_has_property»

    着眼于未来,访问方法层和索引层会分开:截至目前,基于一种访问方法的所有索引将始终具有相同的属性。

    以下四个属性是访问方法的属性(通过«btree»的示例):

    postgres=# select a.*, p.name, pg_indexam_has_property(a.oid,p.name)
    from pg_am a,
         unnest(array['can_order','can_unique','can_multi_col','can_exclude']) p(name)
    where a.amname = 'btree'
    order by a.amname;
     amname | amhandler | amtype |     name      | pg_indexam_has_property 
    --------+-----------+--------+---------------+-------------------------
     btree  | bthandler | i      | can_order     | t
     btree  | bthandler | i      | can_unique    | t
     btree  | bthandler | i      | can_multi_col | t
     btree  | bthandler | i      | can_exclude   | t
    (4 rows)
    

    其中:
    -can_order。
      访问方法使我们能够在创建索引时指定值的排序顺序(目前仅适用于«btree»)。
    -can_unique。
      支持唯一约束和主键(仅适用于«btree»)。
    -can_multi_col。
      可以在多个列上构建索引。
    -can_exclude。
      支持排除约束EXCLUDE。

    以下属性与索引有关(例如,考虑现有索引):

    postgres=# select p.name, pg_index_has_property('t_a_idx'::regclass,p.name)
    from unnest(array[
           'clusterable','index_scan','bitmap_scan','backward_scan'
         ]) p(name);
         name      | pg_index_has_property
    ---------------+-----------------------
     clusterable   | t
     index_scan    | t
     bitmap_scan   | t
     backward_scan | t
    (4 rows)
    

    ·clusterable:

      根据索引重新排序行的可能性(参看cluster命令)

    ·index_scan:

      支持索引扫描。尽管这个特性看起来有点奇怪,但并不是所有的索引可以逐个范围tid。有些一次性返回所有结果,并且只支持位图扫描。

    ·bitmap_scan:

      支持位图扫描

    ·backward_scan:

      结果的返回顺序可以与构建索引时指定的顺序相反。

    最后来看看列的属性

    postgres=# select p.name,
         pg_index_column_has_property('t_a_idx'::regclass,1,p.name)
    from unnest(array[
           'asc','desc','nulls_first','nulls_last','orderable','distance_orderable',
           'returnable','search_array','search_nulls'
         ]) p(name);
            name        | pg_index_column_has_property
    --------------------+------------------------------
     asc                | t
     desc               | f
     nulls_first        | f
     nulls_last         | t
     orderable          | t
     distance_orderable | f
     returnable         | t
     search_array       | t
     search_nulls       | t
    (9 rows)
    

    ·asc, desc, nulls_first, nulls_last, orderable

      这些属性与值的排序有关

    ·distance_orderable

      结果可以按照操作决定的排序顺序返回(目前只是支持GiST和RUM索引)

    ·returnable

      使用索引而不访问表的可能性,即支持index-only 扫描。

    ·search_array

      支持使用表达式«indexed-field IN (list_of_constants)»搜索多个值,它与«indexed-field = ANY(array_of_constants)»相同。

    ·search_nulls

      is null和is not null搜索。

    我们已经详细讨论了一些属性。有些属性是特定于某些访问方法的。我们将在考虑这些具体方法时讨论这些性质。

    操作符类和操作符家族

    除了由接口所描述的公开的访问方法的属性外,还需要了解访问方法接受哪些数据类型和哪些操作符。为此,PostgreSQL引入了操作符类和操作符族的概念。

    操作符类包含索引操作特定数据类型的最小操作符集(可能还有辅助函数)。

    操作符类包含在某个操作符族中。此外,一个通用操作符族可以包含多个操作符类(如果它们具有相同的语义)。例如,«integer_ops»家族包括«int8_ops»、«int4_ops»和«int2_ops»类,它们的类型«bigint»、«integer»和«smallint»大小不同但意义相同:

    postgres=# select opfname, opcname, opcintype::regtype
    from pg_opclass opc, pg_opfamily opf
    where opf.opfname = 'integer_ops'
    and opc.opcfamily = opf.oid
    and opf.opfmethod = (
          select oid from pg_am where amname = 'btree'
        );
       opfname   | opcname  | opcintype
    -------------+----------+-----------
     integer_ops | int2_ops | smallint
     integer_ops | int4_ops | integer
     integer_ops | int8_ops | bigint
    (3 rows)
    

      

    另一个例子:«datetime_ops»家族包含操作日期的操作符类(有时间和没有时间):

    postgres=# select opfname, opcname, opcintype::regtype
    from pg_opclass opc, pg_opfamily opf
    where opf.opfname = 'datetime_ops'
    and opc.opcfamily = opf.oid
    and opf.opfmethod = (
          select oid from pg_am where amname = 'btree'
        );
       opfname    |     opcname     |          opcintype          
    --------------+-----------------+-----------------------------
     datetime_ops | date_ops        | date
     datetime_ops | timestamptz_ops | timestamp with time zone
     datetime_ops | timestamp_ops   | timestamp without time zone
    (3 rows)
    

    操作符族还可以包括其他操作符,用于比较不同类型的值。将操作符类进行分类是为了让计划器为不同类型值的谓词使用索引。一个操作符家族也可以包含辅助函数。

    在大多数情况下,我们不需要了解操作符家族和类。通常我们只创建索引,默认情况下使用特定的操作符类。

    但是,我们可以显式地指定操作符类。这是一个需要显式规范的简单例子:在与C不同的排序规则的数据库中,常规索引不支持LIKE操作:

    postgres=# show lc_collate;
     lc_collate 
    -------------
     en_US.UTF-8
    (1 row)
    
    postgres=# explain (costs off) select * from t where b like 'A%';
             QUERY PLAN          
    -----------------------------
     Seq Scan on t
       Filter: (b ~~ 'A%'::text)
    (2 rows)
    

    我们可以通过使用操作符类«text_pattern_ops»创建一个索引来克服这个限制(注意计划中的条件是如何变化的):

    postgres=# create index on t(b text_pattern_ops);
    
    postgres=# explain (costs off) select * from t where b like 'A%';
                               QUERY PLAN                          
    ----------------------------------------------------------------
     Bitmap Heap Scan on t
       Filter: (b ~~ 'A%'::text)
       ->  Bitmap Index Scan on t_b_idx1
             Index Cond: ((b ~>=~ 'A'::text) AND (b ~<~ 'B'::text))
    (4 rows)
    

    系统目录(system catalog)

    在本文的最后,我们提供了一个与操作符类和族直接相关的系统目录表的简化图。

    系统目录使我们能够在不查看文档的情况下找到许多问题的答案。例如,某个访问方法可以操作哪些数据类型?

    postgres=# select opcname, opcintype::regtype
    from pg_opclass
    where opcmethod = (select oid from pg_am where amname = 'btree')
    order by opcintype::regtype::text;
           opcname       |          opcintype          
    ---------------------+-----------------------------
     abstime_ops         | abstime
     array_ops           | anyarray
     enum_ops            | anyenum
    ...
    

    操作符类包含哪些操作符(以及包含此类操作符的、索引访问可用于条件)?

    postgres=# select amop.amopopr::regoperator
    from pg_opclass opc, pg_opfamily opf, pg_am am, pg_amop amop
    where opc.opcname = 'array_ops'
    and opf.oid = opc.opcfamily
    and am.oid = opf.opfmethod
    and amop.amopfamily = opc.opcfamily
    and am.amname = 'btree'
    and amop.amoplefttype = opc.opcintype;
            amopopr        
    -----------------------
     <(anyarray,anyarray)
     <=(anyarray,anyarray)
     =(anyarray,anyarray)
     >=(anyarray,anyarray)
     >(anyarray,anyarray)
    (5 rows)
    

      

    原文地址:https://habr.com/en/company/postgrespro/blog/442546/

  • 相关阅读:
    Go 语言简介(下)— 特性
    Array.length vs Array.prototype.length
    【转】javascript Object使用Array的方法
    【转】大话程序猿眼里的高并发架构
    【转】The magic behind array length property
    【转】Build Your own Simplified AngularJS in 200 Lines of JavaScript
    【转】在 2016 年做 PHP 开发是一种什么样的体验?(一)
    【转】大话程序猿眼里的高并发
    php通过token验证表单重复提交
    windows 杀进程软件
  • 原文地址:https://www.cnblogs.com/abclife/p/11321618.html
Copyright © 2011-2022 走看看