
正文
postgresql索引无效的简单介绍
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
如何快速掌握 Navicat for PostgreSQL表索引
数据。下面Navicat官网将详解Navicat for PostgreSQL表索引。
方法/步骤
在 Navicat for PostgreSQL“索引”选项卡,只需点击索引栏位即可编辑。使用索引工具栏,便可以创建新的、编辑或删除选定的索引栏位。
● 添加索引:添加一个索引到表。
● 删除索引:删除已选择的索引。
2
名编辑框:设置索引名。没有模式名可以包含在这里,索引总是创建与它的上级表相同的模式。要在索引包含栏位,只需简单地双击栏位或点击“栏位”按钮就能在打开的编辑器中编辑。注意:一些栏位类型不容许由多个栏位索引。
索引方法:下拉列表定义表索引的类型。
3
唯一键:使得索引独一无二,当创建索引以及每次添加数据时,系统检查表中的重复值(如果数据已经存在)。
簇:CLUSTER 指示 PostgreSQL 簇,指定表名和索引名,索引必须已经被定义到表名。当一个表被簇,PostgreSQL 记得它被簇到哪个索引。 CLUSTER 形式表名重新簇表在它之前簇的相同索引。
表空间:创建索引的表空间。
4
限制:如果想创建部分索引,在编辑框输入限制条件。部分索引是一个索引包含项目给一个表的一部分,通常一部分在索引方面较表其余部分更为有用。
注释:定义索引的注释。
栏位编辑器:从名列表选择栏位,也可以使用箭头按钮来改变索引栏位的顺序。
5
排序规则:选择索引的排序规则。支持 PostgreSQL 9.1 或以上版本。
排序顺序:指定排序顺序:ASC 或 DESC。
Nulls 排序:指定 nulls 排序在 non-nulls 前(NULLS FIRST)或后(NULLS LAST)
相关问答
Q1: PostgresQL建立索引如何避免写数据锁定
问题源自一个帅哥在建索引发生表锁的问题。先介绍一下Postgresql的建索引语法: Version:9.1 CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ name ] ON table [ USING method ] ( { column | ( expression ) } [ COLLATE collation ] [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] ) [ WITH ( storage_parameter = value [, ... ] ) ] [ TABLESPACE tablespace ] [ WHERE predicate ] 这里不解释语法的诸多参数使用(排序,使用方法,填充因子等),主要说一下concurrently的使用场景。 正常情况下Postgresql建立普通btree索引时会阻塞DML(insert,update,delete)操作,直到索引完成,期间读操作不受阻塞。当只有一个用户操作这当然没问题,但是在生产环境,并发比较高的情况下,特别是大表建索引就不能这么操作了,不然用户要跳起来骂娘了,点个按钮一天还没反应过来。--使用 Postgresql提供了一个参数,可以在线建立索引的时候避免因写数据而锁表,这个参数叫concurrently。使用很简单,就是用create index concurrently来代替create index即可。--副作用 当然了,使用这个参数是有副作用的,不使用这个参数建索引时DB只扫描一次表,使用这个参数时,会引发DB扫两次表,同时等待所有潜在会读到该索引的事务结束,这么一来,系统的CPU和IO,内存等会受一点影响,所以综合考虑,仍然让用户自行选择,而不是默认。--失败 在使用concurrently参数建索引时,有可能会遇到失败的情况,比如建唯一索引索引发现数据有重复,又或者用户发现建索引时建错字段的,取消建索引操作了。此时该表上会存在一个索引,这是因为带这个参数的建索引命令一经发出,就首先会在系统的日志表里先插一个索引记录进去,又因为这个索引最终建失败了,所以会被标记一个INVALID的状态,如下: postgres=# \d t_kenyon Table public.t_kenyon Column | Type | Modifiers --------+---------+----------- col | integer |Indexes:idx btree (col) INVALID--重建 遇到上述失效的索引重建时两个办法,一个是drop index index_name,然后再执行create index concurrently。还有一个是执行reindex index_name命令,但是后者不支持concurrent参数。--总结
Q2: 在postgresql中为什么索引没有被使用
可能的原因:
1) 如果查询的目标表中数据量很少的情况下,PostgreSQL不会走索引查询的,而是直接顺序查找;
2) 查询的条件中并未直接使用索引的字段,或者字段不完整;
Q3: postgresql关闭和打开索引
在安装postgresql时,索引都是默认开启的,具体的可以在postgresql.conf中去找。
还有就是,你为什么要关掉索引恩?
Q4: Postgresql 建索引性能优化
客户新上线了一套监控系统,可以监控到所有的执行慢的SQL,监控到有个批量任务导入大量数据后,进行索引创建。耗时需要几分钟,虽然不影响业务,但是需要整改。
这种问题的处理思路,都是大拆小,搞并发。
在测试环境,创建一个大表进行测试,创建大量的假数据。
创建表
随机字符串生成函数
生成大量的数据
经测试发现这种方法创建数据太慢了,改成使用COPY的方式创建数据。
排查发现random_string效率太低,生成一条数据接近1ms
重新创建表
写程序创建8600万条数据放在test.csv中
导入大量数据
测试基准数据
\timing 开启计时
耗时532824.434 ms
耗时385838.893 ms,提升 38%的性能,非常不错,但是远远不够。
仍然会出发告警。
重新创建表
创建分区
并发创建INDEX,并记录每个分区索引创建的开始时间和结束时间;
耗时 = 最大结束时间 - 最小开始时间 = 137 s,速度提升接近4倍。
顺序创建INDEX,并记录每个分区索引创建的开始时间和结束时间;
耗时 = 每个索引的耗时相加 = 457358.14 ms,速度提升 16.5%
顺序创建INDEX,优化并发
耗时 = 每个索引的耗时相加 = 292027.642 ms, 速度提升接近两倍。
在开启了并发参数的情况下,如果再叠加并发分区INDEX创建,会不会有惊喜呢?
并发创建INDEX,并记录每个分区索引创建的开始时间和结束时间;
耗时 = 最大结束时间 - 最小开始时间 = 141 s,速度还不如默认并发参数下的表现。应该是资源发生争抢导致的,通过系统监控发现CPU已经打满了。
分区并发是目前能想到的最优化手段了。
还需要结合查询的情况进行分析,分区会带来一点点的性能下降是否影响也需要考虑一下。
分区时目前能避开监控报警的唯一手段了,另外还钻了监控报警的空子。
客户的监控是基于单条语句的,单个分区的最大创建时间为47s,控制在分钟以内了。
Q5: postgresqL 的Btree 与gin索引
一.gin索引需要安装第三方插件
yum install postgresql96-contrib -- 安装插件
find / -name extension --可以看到btree_gin.control存在
create extension btree_gin; -- 添加索引
二.测试数据基本属性介绍
总共使用3个表,表结构和数据量完全一致。
表数据量:10522369
表字段:id ,basic_acc_no,id_card,name,sex,telephone,json_t
1)索引的配置情况:
basic_account_info_al -- btree
basic_account_info_al2 --gin
basic_account_info_al3 -- btree multi
basic_account_info_al 单列索引 id,basic_acc_no,name,json_t
basic_account_info_al2 gin索引 (id,basic_acc_no,id_card,name),(json_t)
basic_account_info_al3 复合索引 (id,basic_acc_no),(name,id)(json_t,id)
basic_account_info_al 表达式索引 (json_t-id)
basic_account_info_al2表达式索引 ((json_t-'id'))
三.测试结果
1.唯一值属性:索引字段都是唯一 id,basic_acc_no
查询语句
explain analyse select * from basic_account_info_al2 where id = 29699221 ;
explain analyse select * from basic_account_info_al where id = 29699221 ;
explain analyse select * from basic_account_info_al3 where id = 29699221 ;
explain analyse select * from basic_account_info_al2 where basic_acc_no = 'XFK2990134' ;
explain analyse select * from basic_account_info_al where basic_acc_no = 'XFK2990134' ;
explain analyse select * from basic_account_info_al3 where basic_acc_no = 'XFK2990134' ;
explain analyse select * from basic_account_info_al2 where basic_acc_no = 'XFK9780134' and id = 29699221;
explain analyse select * from basic_account_info_al where basic_acc_no = 'XFK9780134' and id = 29699221;
explain analyse select * from basic_account_info_al3 where basic_acc_no = 'XFK9780134' and id = 29699221;
explain analyse select * from basic_account_info_al2 where id = 29699221 and basic_acc_no = 'XFK9780134' ;
explain analyse select * from basic_account_info_al where id = 29699221 and basic_acc_no = 'XFK9780134' ;
explain analyse select * from basic_account_info_al3 where id = 29699221 and basic_acc_no = 'XFK9780134' ;
2.重复值属性: name是有重复值的。
explain analyse select * from basic_account_info_al where name ='张燕洪';
explain analyse select * from basic_account_info_al3 where name ='张燕洪';
explain analyse select *from basic_account_info_al2 where name ='张燕洪';
explain analyse select * from basic_account_info_al2 where id = 24426014 and name = '周杨' ;
explain analyse select * from basic_account_info_al where id = 24426014 and name = '周杨' ;
explain analyse select * from basic_account_info_al3 where id = 24426014 and name = '周杨' ;
explain analyse select * from basic_account_info_al2 where name = '周杨' and id = 24426014 ;
explain analyse select * from basic_account_info_al where name = '周杨' and id = 24426014 ;
explain analyse select * from basic_account_info_al3 where name = '周杨' and id = 24426014 ;
3.jsonb属性
create index inx_gin_json on basic_account_info_al2 using gin (json_t);
create index inx_btree_json on basic_account_info_al (json_t);
create index inx_btree_2_js on basic_account_info_al3 (json_t,id );
explain analyse select * from basic_account_info_al where json_t ='{"id": 21782879, "sex": 0, "name": "刘乐典"}';
explain analyse select * from basic_account_info_al2 where json_t ='{"id": 21782879, "sex": 0, "name": "刘乐典"}';
explain analyse select * from basic_account_info_al3 where json_t ='{"id": 21782879, "sex": 0, "name": "刘乐典"}';
explain analyse select * from basic_account_info_al WHERE json_t @ '{"id": 21782879}';
explain analyse select * from basic_account_info_al2 WHERE json_t @ '{"id": 21782879}';
explain analyse select * from basic_account_info_al3 WHERE json_t @ '{"id": 21782879}';
explain analyse select * from basic_account_info_al where (json_t-id)= '24426014' ;
explain analyse select * from basic_account_info_al2 where (json_t-id)= '24426014' ;
explain analyse select * from basic_account_info_al3 where (json_t-id)='24426014' ;
4.jsonb表达式索引
查询条件 表名 查询时使用的索引名称 查询时间(5次平均)/ms
(json_t-id)= '24426014' basic_account_info_al inx_json_id 0.040
basic_account_info_al3 inx_json_id_2 0.039
explain analyse select * from basic_account_info_al where (json_t-id)= '24426014' ;
explain analyse select * from basic_account_info_al2 where (json_t-id)= '24426014' ;
四.获相同的结果使用Jsonb与btree对比
jsonb支持两种特有的GIN索引jsonb_ops和jsonb_path_ops。 jsonb_ops调用gin_extract_jsonb函数生成key,每个键和值都作为一个单独的索引项。而jsonb_path_ops使用函数gin_extract_jsonb_path抽取:只为每个值创建一个索引项。{“foo”:{“bar”,”baz”}}, jsonb_ops生成3个索引项,jsonb_path_ops由foo,bar,baz组合一个hash值作为一个索引项。jsonb_path_ops索引要比jsonb_ops的小很多,性能上也会有所提升。
create index inx_gin_patn_json ON public.basic_account_info_al4 USING gin (json_t jsonb_path_ops); -- jsonb_path_ops
create index inx_gin_json on basic_account_info_al2 using gin (json_t); --jsonb_ops
1.精确查询
2.范围查询
下表显示了gin索引对于jsonb数据类型可使用的操作符。
名称 索引数据类型 可索引操作符
jsonb_ops jsonb ? ? ?| @
json_path_ops jsonb @
注:? ? ?| 索引key是否包含在jsonb中
对于范围(json_t-'id') 20000079,这样的条件 gin索引不起作用, 这里采用表达式索引方式,查询条件的两边数据类型相同才可以做索引查询,否则全表扫描。
CREATE INDEX inx_json_id_2 ON public.basic_account_info_al2 USING btree (((json_t-'id')::int));
总结: 当仅有一个条件查询时,gin索引与btree索引的性能差异不大,但有多个条件查询时,gin,btree单
列索引没有btree复合索引的性能高。jsonb是以二进制格式存储且不保证键的顺序。可以使用表达式索引指定到jsonb的具体键值,但是如果不能提前知道查询数据中的哪个键,确定定义GIN索引和使用@(或者其他有利于索引的操作符)查询。
五.jsonb添加数据属性
例如:
{"id":20000241,"name":"陈敏","sex":1} - {"age":"18","id":20000241,"name":"陈敏","sex":1}
一旦创建了索引,就不需要进一步的干预:当表被修改时,系统将更新索引,当执行计划认为使用索引比顺序的表扫描更有效的时候,它会使用索引。
UPDATE basic_account_info_al4 SET json_t = json_t || '{"age":"18"}'::jsonb; -- 更新语句
gin索引名称 索引方式 修改前大小 修改后大小 带索引更新时间
inx_gin_patn_json jsonb_path_ops 574M 615M 643561.004 ms
inx_gin_json jsonb_ops 665M 695M 时间过长超过1h
jsonb_ops方式建立的索引大量更新时,执行时间太长。当插入更新时gin索引比较慢,如果要向一张大表中插入大量数据时,最好先把gin索引删除,插入数据后再重建索引。
当json_t为{"id":20000241,"name":"陈敏","sex":1} 数据量为10522369 创建gin索引时间
130372.955 ms
当json_t为{"age":"18","id":20000241,"name":"陈敏","sex":1} 数据量为10522369 创建gin索引时间
148971.011 ms
postgresql索引无效的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于、postgresql索引无效的信息别忘了在本站进行查找喔。







