`

PostgreSQL-学习-06--索引

阅读更多

PostgreSQL 提供了好几种索引类型:B-tree, Hash, GiST, GIN 。每种索引类型都比较适合某些特定的查询类型,因为它们用了不同的算法。

B-tree

CREATE TABLE test1 (

        id integer,

        content varchar

    );

    CREATE INDEX test1_id_index ON test1 (id);    

    B-Tree索引主要用于等于和范围查询,特别是当索引列包含操作符" <、<=、=、>=和>"作为查询条件时,PostgreSQL的查询规划器都会考虑使用B-Tree索引。在使用BETWEEN、IN、IS NULL和IS NOT NULL的查询中,PostgreSQL也可以使用B-Tree索引。然而对于基于模式匹配操作符的查询,如LIKE、ILIKE、~和 ~*,仅当模式存在一个常量,且该常量位于模式字符串的开头时,如col LIKE 'foo%'或col ~ '^foo',索引才会生效,否则将会执行全表扫描,如:col LIKE '%bar'。

Hash

CREATE INDEX name ON table USING hash (column);

    散列(Hash)索引只能处理简单的等于比较。当索引列使用等于操作符进行比较时,查询规划器会考虑使用散列索引。

    这里需要额外说明的是,PostgreSQL散列索引的性能不比B-Tree索引强,但是散列索引的尺寸和构造时间则更差。另外,由于散列索引操作目前没有记录WAL日志,因此一旦发生了数据库崩溃,我们将不得不用REINDEX重建散列索引

GiST

不是单独一种索引类型,而是一种架构,可以在这种架构上实现很多不同的索引策略。因此,可以使用 GiST 索引的特定操作符类型高度依赖于索引策略(操作符类)。

作为示例,PostgreSQL 的标准发布中包含用于二维几何数据类型的 GiST 操作符类,它支持<<、&<、&>、>>、<<|、&<|、|&>、|>>、@>、<@、~=、&& 操作符的索引查询。这些操作符的含义参见。 许多其它 GiST 操作符类位于 contrib 中,或者是单独的项目,更多信息参见。

GIN 

反转索引,它可以处理包含多个键的值(比如数组)。与 GiST 类似,GIN 支持用户定义的索引策略,可以使用 GIN 索引的特定操作符类型根据索引策略的不同而不同。、

作为示例,PostgreSQL 的标准发布中包含用于一维数组的 GIN 操作符类,它支持<@、@>、=、&& 操作符的索引查询。这些操作符的含义参见。 许多其它 GIN 操作符类位于 contrib, tsearch2, intarray 模块。更多信息参见

 

二、复合索引

PostgreSQL中的索引可以定义在数据表的多个字段上,如:

    CREATE TABLE test2 (

        major int,

        minor int,

        name varchar

    }

    CREATE INDEX test2_mm_idx ON test2 (major, minor);

    在当前的版本中,只有B-tree、GiST和GIN支持复合索引,其中最多可以声明32个字段。

    1. B-Tree类型的复合索引:

    在B-Tree类型的复合索引中,该索引字段的任意子集均可用于查询条件,不过,只有当复合索引中的第一个索引字段(最左边)被包含其中时,才可以获得最高效率。

    

    2. GiST类型的复合索引:

    在GiST类型的复合索引中,只有当第一个索引字段被包含在查询条件中时,才能决定该查询会扫描多少索引数据,而其他索引字段上的条件只是会限制索引返回的条目。假如第一个索引字段上的大多数数据都有相同的键值,那么此时应用GiST索引就会比较低效。 

 

    3. GIN类型的复合索引:

    与B-Tree和GiST索引不同的是,GIN复合索引不会受到查询条件中使用了哪些索引字段子集的影响,无论是哪种组合,都会得到相同的效率。

 

    使用复合索引应该谨慎。在大多数情况下,单一字段上的索引就已经足够了,并且还节约时间和空间。除非表的使用模式非常固定,否则超过三个字段的索引几乎没什么用处。 

 

三、组合多个索引:

 

    PostgreSQL可以在查询时组合多个索引(包括同一索引的多次使用),来处理单个索引扫描不能实现的场合。与此同时,系统还可以在多个索引扫描之间组成AND和OR的条件。比如,一个类似WHERE x = 42 OR x = 47 OR x = 53 OR x = 99的查询,可以被分解成四个独立的基于x字段索引的扫描,每个扫描使用一个查询子句,之后再将这些扫描结果OR在一起并生成最终的结果。另外一个例子是,如果我们在x和y上分别存在独立的索引,那么一个类似WHERE x = 5 AND y = 6的查询,就会分别基于这两个字段的索引进行扫描,之后再将各自扫描的结果进行AND操作并生成最终的结果行。

    为了组合多个索引,系统扫描每个需要的索引,然后在内存里组织一个BITMAP,它将给出索引扫描出的数据在数据表中的物理位置。然后,再根据查询的需要,把这些位图进行AND或者OR的操作并得出最终的BITMAP。最后,检索数据表并返回数据行。表的数据行是按照物理顺序进行访问的,因为这是位图的布局,这就意味着任何原来的索引的排序都将消失。如果查询中有ORDER BY子句,那么还将会有一个额外的排序步骤。因为这个原因,以及每个额外的索引扫描都会增加额外的时间,这样规划器有时候就会选择使用简单的索引扫描,即使有多个索引可用也会如此。     

 

    

四、唯一索引:

 

    目前,只有B-Tree索引可以被声明为唯一索引。

    CREATE UNIQUE INDEX name ON table (column [, ...]);

    如果索引声明为唯一索引,那么就不允许出现多个索引值相同的行。我们认为NULL值相互间不相等。

    

五、表达式索引:

 

    表达式索引主要用于在查询条件中存在基于某个字段的函数或表达式的结果与其他值进行比较的情况,如:

    SELECT * FROM test1 WHERE lower(col1) = 'value';

    此时,如果我们仅仅是在col1字段上建立索引,那么该查询在执行时一定不会使用该索引,而是直接进行全表扫描。如果该表的数据量较大,那么执行该查询也将会需要很长时间。解决该问题的办法非常简单,在test1表上建立基于col1字段的表达式索引,如:

    CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1));

    如果我们把该索引声明为UNIQUE,那么它会禁止创建那种col1数值只是大小写有区别的数据行,以及col1数值完全相同的数据行。因此,在表达式上的索引可以用于强制那些无法定义为简单唯一约束的约束。现在让我们再看一个应用表达式索引的例子。

    SELECT * FROM people WHERE (first_name || ' ' || last_name) = 'John Smith';

    和上面的例子一样,尽管我们可能会为first_name和last_name分别创建独立索引,或者是基于这两个字段的复合索引,在执行该查询语句时,这些索引均不会被使用,该查询能够使用的索引只有我们下面创建的表达式索引。

    CREATE INDEX people_names ON people ((first_name || ' ' || last_name));

    CREATE INDEX命令的语法通常要求在索引表达式周围书写圆括弧,就像我们在第二个例子里显示的那样。如果表达式只是一个函数调用,那么可以省略,就像我们在第一个例子里显示的那样。

    从索引维护的角度来看,索引表达式要相对低效一些,因为在插入数据或者更新数据的时候,都必须为该行计算表达式的结果,并将该结果直接存储到索引里。然而在查询时,PostgreSQL就会把它们看做WHERE idxcol = 'constant',因此搜索的速度等效于基于简单索引的查询。通常而言,我们只是应该在检索速度比插入和更新速度更重要的场景下使用表达式索引。 

    

六、部分索引:

 

    部分索引(partial index)是建立在一个表的子集上的索引,而该子集是由一个条件表达式定义的(叫做部分索引的谓词)。该索引只包含表中那些满足这个谓词的行。

    由于不是在所有的情况下都需要更新索引,因此部分索引会提高数据插入和数据更新的效率。然而又因为部分索引比普通索引要小,因此可以更好的提高确实需要索引部分的查询效率。见以下三个示例:

    1. 索引字段和谓词条件字段一致:

    CREATE INDEX access_log_client_ip_ix ON access_log(client_ip)

        WHERE NOT (client_ip > inet '192.168.100.0' AND client_ip < inet '192.168.100.255');

    下面的查询将会用到该部分索引:

    SELECT * FROM access_log WHERE url = '/index.html' AND client_ip = inet '212.78.10.32';

    下面的查询将不会用该部分索引:

    一个不能使用这个索引的查询可以是∶

    SELECT * FROM access_log WHERE client_ip = inet '192.168.100.23';

 

    2. 索引字段和谓词条件字段不一致:

    PostgreSQL支持带任意谓词的部分索引,唯一的约束是谓词的字段也要来自于同样的数据表。注意,如果你希望你的查询语句能够用到部分索引,那么就要求该查询语句的条件部分必须和部分索引的谓词完全匹配。 准确说,只有在PostgreSQL能够识别出该查询的WHERE条件在数学上涵盖了该索引的谓词时,这个部分索引才能被用于该查询。

    CREATE INDEX orders_unbilled_index ON orders(order_nr) WHERE billed is not true;

    下面的查询一定会用到该部分索引:

    SELECT * FROM orders WHERE billed is not true AND order_nr < 10000;

    那么对于如下查询呢?

    SELECT * FROM orders WHERE billed is not true AND amount > 5000.00;

    这个查询将不像上面那个查询这么高效,毕竟查询的条件语句中没有用到索引字段,然而查询条件"billed is not true"却和部分索引的谓词完全匹配,因此PostgreSQL将扫描整个索引。这样只有在索引数据相对较少的情况下,该查询才能更有效一些。

    下面的查询将不会用到部分索引。

    SELECT * FROM orders WHERE order_nr = 3501;

    

    3. 数据表子集的唯一性约束:

    CREATE TABLE tests (

        subject text,

        target text,

        success boolean,

        ...

    );

    CREATE UNIQUE INDEX tests_success_constraint ON tests(subject, target) WHERE success;

    该部分索引将只会对success字段值为true的数据进行唯一性约束。在实际的应用中,如果成功的数据较少,而不成功的数据较多时,该实现方法将会非常高效。

     

七、检查索引的使用:

 

    见以下四条建议:

    1. 总是先运行ANALYZE。

    该命令将会收集表中数值分布状况的统计。在估算一个查询返回的行数时需要这个信息,而规划器则需要这个行数以便给每个可能的查询规划赋予真实的开销值。如果缺乏任何真实的统计信息,那么就会使用一些缺省数值,这样肯定是不准确的。因此,如果还没有运行ANALYZE就检查一个索引的使用状况,那将会是一次失败的检查。 

    2. 使用真实的数据做实验。

    用测试数据填充数据表,那么该表的索引将只会基于测试数据来评估该如何使用索引,而不是对所有的数据都如此使用。比如从100000行中选1000行,规划器可能会考虑使用索引,那么如果从100行中选1行就很难说也会使用索引了。因为100行的数据很可能是存储在一个磁盘页面中,然而没有任何查询规划能比通过顺序访问一个磁盘页面更加高效了。与此同时,在模拟测试数据时也要注意,如果这些数据是非常相似的数据、完全随机的数据,或按照排序顺序插入的数据,都会令统计信息偏离实际数据应该具有的特征。    

    3. 如果索引没有得到使用,那么在测试中强制它的使用也许会有些价值。有一些运行时参数可以关闭各种各样的查询规划。

    4. 强制使用索引用法将会导致两种可能:一是系统选择是正确的,使用索引实际上并不合适,二是查询计划的开销计算并不能反映现实情况。这样你就应该对使用和不使用索引的查询进行计时,这个时候EXPLAIN ANALYZE命令就很有用了 

分享到:
评论

相关推荐

    postgresql-10.12-1-linux-x64-binaries.tar.gz

    **标签“PostgreSQL”相关的学习资源和社区:** 1. 官方文档:提供详细的使用指南和API参考,地址为https://www.postgresql.org/docs/。 2. PostgreSQL中国社区:国内的用户交流平台,有大量技术文章和问题解答,...

    Postgresql-9.6.1-1-初级手册-安装及使用

    【PostgreSQL 9.6.1 初级手册:安装与使用】 PostgreSQL 是一个功能强大...以上就是PostgreSQL 9.6.1在Linux和Windows平台上的安装与基础使用方法,通过学习这些知识,您可以快速上手PostgreSQL并开始数据库管理工作。

    postgresql-9.5.0-1-windows 32位

    PostgreSQL是一种开源关系型数据库管理系统(RDBMS),在IT领域广泛应用,特别是在需要高度可靠性和复杂查询的场景中。...通过深入学习和掌握PostgreSQL,你可以构建高效、稳定和可扩展的数据库应用。

    postgresql-9.1.1-1-windows-binaries

    PostgreSQL 是一个强大的开源对象关系型数据库管理系统,其9.1.1版本是该系统的一个稳定发行版。...虽然这个版本现在已经较旧,但了解其特性和操作方式对于学习和理解PostgreSQL的历史和发展仍然很有价值。

    PostgreSQL-11.1-1 Windows64位

    - PostgreSQL拥有活跃的开发者社区和用户群,提供及时的技术支持和丰富的学习资源。 - 社区不断推出新版本,修复已知问题,添加新功能,保证系统的持续进步。 总结,PostgreSQL 11.1作为一款64位的Windows数据库...

    51CTOマツヤリ-postgresql-9.2.4-1-windows.zip

    描述中的内容 "51CTOマツヤリ-postgresql-9.2.4-1-windows.zip" 与标题相同,暗示这可能是从知名 IT 学习平台 51CTO 下载的 PostgreSQL 安装包,用于在 Windows 环境下安装和配置数据库服务器。 标签 "postgresql" ...

    postgresql--内核分析--逻辑备份还原

    这些博客资源对于学习和深入理解PostgreSQL的逻辑备份还原提供了丰富的参考资料,包括备份文件的结构、恢复过程的技巧以及面对特定问题时的解决方案。 ### 总结 PostgreSQL的逻辑备份还原是一个复杂但至关重要的...

    PostgreSQL-9.0-High-Performance2010

    - **新特性介绍**:PostgreSQL 9.0 是一个重要的里程碑版本,它引入了许多新功能,包括支持热备、增强的复制功能(物理复制和流复制)、新的索引类型(如GiST、SP-GiST、GIN和BRIN)等。 - **性能提升**:此版本在...

    postgresql-9.5.1.tar.gz

    - 监控数据库性能,分析 `pg_stat_activity` 视图,查看 `pg_stat_user_tables` 和 `pg_stat_user_indexes` 获取索引和表的统计信息。 **5. 扩展与开发** - PostgreSQL 支持编写自定义函数,例如使用 PL/pgSQL 或...

    postgresql-10 官方文档

    ### PostgreSQL 10.3 官方文档知识点总结 #### 一、PostgreSQL 简介 - **定义**:PostgreSQL 是一个功能...通过学习这些内容,用户可以更好地理解 PostgreSQL 的工作原理,并掌握如何高效地使用这一强大的数据库系统。

    postgresql-11.2.1win64.zip

    2. **并行操作增强**:PostgreSQL 11引入了更多的并行化操作,如并行扫描、索引构建和VACUUM,这些改进进一步提升了多核CPU环境下的性能。 3. **存储过程语言支持**:PostgreSQL支持多种存储过程语言,如PL/pgSQL,...

    postgresql-16.1.tar.gz

    PostgreSQL是一种开源关系型数据库管理系统(RDBMS),在Linux平台上广泛应用。...在实际应用中,还需要学习SQL语言、事务处理、索引策略、复制与高可用性等相关知识,以充分利用PostgreSQL的强大功能。

    postgresql-9.2.3.tar.gz

    - PostgreSQL拥有活跃的社区,提供详尽的文档和在线帮助,方便用户解决问题和学习。 综上所述,"postgresql-9.2.3.tar.gz"是一个包含PostgreSQL数据库系统9.2.3版本源代码的压缩包,适合开发者进行深度开发、定制...

    postgresql-10.1-3-windows-x64.zip

    数据库是存储和管理数据的系统,PostgreSQL作为其中一种,其SQL语法、数据类型、事务处理和安全性等都是学习的重点。Python是常用的数据分析和脚本语言,与PostgreSQL结合可以实现高效的数据操作和自动化任务。对于...

    postgresql-11官方文档

    总的来说,"postgresql-11官方文档"是学习和参考PostgreSQL 11的权威资料,通过深入阅读和实践,你可以全面掌握这个强大开源数据库的使用。解压后的"postgresql-11-A4.pdf"文件,是你探索这个数据库世界的起点。

    PostgreSQL-90-High-Performance.pdf

    《PostgreSQL-9.0-High-Performance》是由Gregory Smith撰写的一本专注于提升PostgreSQL数据库性能的...通过学习和应用本书提供的知识,读者可以更好地管理和优化PostgreSQL数据库,从而在实际工作中提升性能和效率。

    postgresql-9.6.11-1-windows-x64

    postgresql-9.6.11-1-windows-x64位可安装,用于学习交流,下载安装可用 请勿用于商业用途,如有版权纠纷,本人概不负责! 1. PostgreSQL完全免费,而且是BSD协议. 2. 与PostgreSQl配合的开源软件很多,有很多分布式...

    【批量下载】timescaledb-postgresql-11_1.3.0-windows-amd64等.zip

    《批量下载timescaledb-postgresql-11_1.3.0-windows-amd64等.zip:探索PostgreSQL与TimescaleDB的时序数据库魅力》 在数字化时代,数据的生成速度飞速增长,尤其在物联网(IoT)、监控系统、金融交易等领域,时序...

    PostgreSQL11.2-CN-v1.1等.zip

    通过这份中文手册,无论是开发者、数据库管理员还是学习者,都能深入理解PostgreSQL的架构、语法和最佳实践,从而更高效地利用这个强大的数据库系统。对于团队协作,手册中的例子和解释也能帮助大家统一代码风格和...

    DB2-PostgreSQL-源码

    5. **扩展性**:PostgreSQL的一大特点是其强大的扩展性,允许用户通过插件开发自定义的数据类型、函数和索引。对比DB2,虽然扩展性相对有限,但IBM提供了丰富的工具和API来满足不同需求。 6. **安全性与合规性**:...

Global site tag (gtag.js) - Google Analytics