为什么不走索引, PostgreSQL

原文出处:
<!http://www.postgresonline.com/journal/archives/78-why-si-my-index-not-being-used.html>
有一个老的问题经常会问道数据库转件就是为什么或者为什么表的索引没有被使用?
下面的文章将会简单的回答这个常见的问题,并按着统计学意义排序。

一、对于外行人来说,你怎么知道索引没有被使用呢?
可以使用 EXPLAIN ; EXPLAIN ANALYZE 或者 pgadmin 的图形执行计划来查看。 <!http://www.postgresonline.com/journal/archives/27-Reading-PgAdmin-Graphical-Explain-Plans.html>
如果查询语句确实没有走索引,那么我们应该怎么做呢?
1. 原因: 过时的统计信息。如果你的数据库 auto-vacuum 选项是打开的, 那么就不会引起这个问题的发生。但是如果你最近刚批量的导入数据,且新建了索引,那么很有可能,统计信息过期,导致查询优化器不能获得最新的统计信息,做出正确的判断。
方案: vacuum analyze verbose sometable_name;
这里增加了 verbose 参数,是因为它可以使你看的更清晰 vacuum 是如何运作的。

  1. 原因: 查询优化器认为选择 table scan 要比选择 index scan 更快: 做出这种选择的原因是,查询涉及的表太小了, 或者我们构建索引的字段重复值太多。
    方案: 对于 布尔字段构建索引可以认为不是很重要,因为一半是数据,另一半也是数据。不过对这种字段构建部分索引是最好的选择,值索引活动的数据。
  2. 构建的索引与实际过滤字段的方式不兼容。这里有很多种解决方法
    3.1 LIKE %me 将永远不会选择索引扫描, 但是 LIKE me% 就有可能选择索引扫描
    3.2 大小写的陷阱,例子如下

    
     CREATE INDEX idx_faults_name ON faults USING btree (fault_name);     --- 构建的索引
     --- 查询语句如下
     SELECT * FROM faults WHERE UPPER(FAULT_NAME) LIKE 'CAR%' Possible fix;
    --- 解决办法如下
     CREATE INDEX idx_faults_name ON faults  USING BTREE (upper(fault_name));
    

    3.3 这个问题很难被意识到, 通过阅读别人的问题,你就会更好的发现问题。这个问题涉及到了 运算符类
    https://www.postgresql.org/message-id/49075E5E.6040701@gmail.com 知道这个问题的解决方法的人很少

    The other point is that in non-C locales, a standard varchar index isn't

    usable for LIKE (the sort order is usually wrong). You can re-initdb
    in C locale or create a varchar_pattern_ops index.
    booktown=# create index first_name_idx_vpo on auth using btree
    (first_name varchar_pattern_ops);

    解决方案如下:

    
      CREATE INDEX idx_faults_uname_varcahr_parttern on faluts USING BTREE (UPPER (fault_name) varchar_parttern_ops);

    看到这个解决方案,可能还需要下面的变体和 IN 子句才能解决问题。
    我们并不能证明这是数据库编码的问题, 数据的不同或者数据库版本的不同。 8。2 , 8.3 。 对于pg8.3 我们推荐使用 UTF-8 的编码方式初始化数据库。而对于 8.2 版本是使用的 SQL-ASCII, 这个参数 varcahr_pattern_ops 对于 like 语句是足够解决的。

    
      CREATE INDEX idx_faults_uname ON faults USING btree (upper (falut_name));
    

    SELECT fault_name from faults WHERE upper(fault_name) IN ( 'CASCADIA ABDUCTION', 'CABIN FEVER');

    3.4 不兼容的数据类型。
    例如, 我们为日期类型构建索引,但是却通过将日期类型转换为 text 类型, 用在比较语句中, 是不选索引扫描的。

    1. 并不是所有的索引都会被使用。 尽管 pg8.1以上的版本开始支持 Bitmap Index scan. 该索引扫描允许一个表上构建多个索引, 在查询执行时,将这些索引构建为 内存位图的形式。 如果你构建了很多索引, 不要期望全部候选索引都会被用到。有些时候,执行 table scan 会更高效。
    2. 问题: 查询优化器的不完美。
      方案: 期待更美好的查询优化器的产生。 事实上, postgresql 优化器的能力很不错的。*If only I could provide hints, I could make this faster *.最好的解决方案就是让查询优化器变的更好。随着数据库的变化, 优化器也随之变化, 这就是数据库编程不同于其他编程的原因。
时间: 2024-09-29 03:48:50

为什么不走索引, PostgreSQL的相关文章

有时一个表的某个字段明明有索引,当观察一些语句的执行计划确不走索引呢?如何解决 ?

为什么有时一个表的某个字段明明有索引,当观察一些语的执行计划确不走索引呢?如何解决呢 ? A.不走索引大体有以下几个原因 你在Instance级别所用的是all_rows的方式 你的表的统计信息(最可能的原因) 你的表很小,上文提到过的,Oracle的优化器认为不值得走索引. B.解决方法 可以修改init<SID>.ora中的OPTIMIZER_MODE这个参数,把它改为Rule或Choose,重起数据库.也可以使用4中所提的Hint. 删除统计信息 SQL>analyze table

已建索引执行计划为何不走索引?

DROP INDEX scott.IDX_UNI_EMP; CREATE INDEX scott.IDX_EMP_1 ON scott.EMPLOYEE (EMPLOYEE_ID); -- SELECT* FROMscott.EMPLOYEE WHEREEMPLOYEE_ID = 100; SELECT* FROMTABLE (DBMS_XPLAN.DISPLAY_CURSOR (NULL, NULL, 'ADVANCED')); -- TRUNCATE TABLE scott.EMPLOYEE

改写不走索引的SQL

如下SQL为保证所有数据都出自UP_LOAD_SERL10表(后面将以别名T3称呼此表,其他表也已别名称呼) SELECT        T1.SERL_NO       ,T1.SI_YMD       ,T1.ST_YMD       ,T1.ST2_YMD       ,T1.SO_YMD         ,T1.ACTU_DT    FOTA_DT       ,T2.SALE_YMD  CHANEL_SO       ,T2.REGI_DT   CHANEL_SO_REGI_DT FR

不走索引场景的一次分析优化

  一般一个SQL查询数据量很大,且优化余地不大时,我们必然想开启并行,用并行的方式提高数据的查询速度,然后不是任何情况下开启并行都可以达到最佳运行效果, 有时原本使用索引的执行计划,因为使用并行反而该走全表扫描,因此必须通过hint方式引导优化器采取正确的执行计划,对于如下SQL SELECT                         T1.RPO_NO                     ,T_LGIN.LGIN_DT                     ,T_LGIN.USE

SQL SERVER参数化查询后不走筛选索引

DROP TABLE T_TEST CREATE TABLE T_TEST( ID INT IDENTITY PRIMARY KEY,STATUS BIT ) INSERT INTO T_TEST SELECT 0 GO 100000 INSERT INTO T_TEST SELECT 1 CREATE INDEX IXF_T_TEST_STATUS ON T_TEST(STATUS) WHERE STATUS=1 UPDATE STATISTICS T_TEST with fullscan D

PostgreSQL 9种索引的原理和应用场景

标签 PostgreSQL , btree , hash , gin , gist , sp-gist , brin , bloom , rum , zombodb , bitmap 背景 PostgreSQL 拥有众多开放特性,例如 1.开放的数据类型接口,使得PG支持超级丰富的数据类型,除了传统数据库支持的类型,还支持GIS,JSON,RANGE,IP,ISBN,图像特征值,化学,DNA等等扩展的类型,用户还可以根据实际业务扩展更多的类型. 2.开放的操作符接口,使得PG不仅仅支持常见的类型

从难缠的模糊查询聊开 - PostgreSQL独门绝招之一 GIN , GiST , SP-GiST , RUM 索引原理与技术背景

标签 PostgreSQL , gist , sp-gist , gin , rum index , 模糊查询 , 搜索引擎 , token位置搜索 , pg_hint_plan , 自动优化 , 分词 , like '%xxx%' 背景 模糊查询,是一个需求量很大,同时也是一个对数据库来说非常难缠的需求. 对于前模糊(like '%xxx'),可以使用倒排B-TREE索引解决,对于后模糊(like 'xxx%'),可以使用B-TREE索引解决. B-TREE索引通常支持的查询包括 > , <

PostgreSQL 数据库开发规范

PostgreSQL 数据库开发规范 背景 PostgreSQL的功能非常强大,但是要把PostgreSQL用好,开发人员是非常关键的. 下面将针对PostgreSQL数据库原理与特性,输出一份开发规范,希望可以减少大家在使用PostgreSQL数据库过程中遇到的困惑. 目标是将PostgreSQL的功能.性能发挥好,她好我也好. PostgreSQL 使用规范 命名规范 [强制]库名.表名限制命名长度,建议表名及字段名字符总长度小于等于63. [强制]对象名(表名.列名.函数名.视图名.序列名

Greenplum 类型一致性使用规范 - 索引条件、JOIN的类型一致性限制

标签 PostgreSQL , Greenplum , 类型一致 , 索引 , inner转换 , join 背景 在查询时,有很多用户会犯浑,发现建立了索引,但是查询偏偏不走索引. 怎么不走索引啊? 这里做容易混淆的是类型的差异,例如字段类型为字符串,但是输入的是INT类型,这样就可能不走索引.(除非创建了自动的CAST,自动进行类型转换) 查询的输入类型与索引的类型一致是非常有必要的. 例子 1.建表(使用变长.定长字符串类型),写入测试数据 create table tbl3(id int