首页 > 其他分享 >KingbaseES 语句like前匹配如何使用索引

KingbaseES 语句like前匹配如何使用索引

时间:2023-05-09 19:45:45浏览次数:47  
标签:语句 rows like .. text system test KingbaseES name

前言

有现场同事反馈 sql语句 like 使用后缀通配符 % 不走索引。
至于执行计划没走索引的原因与KingbaseES数据库中的排序规则相关。

测试

测试环境:

KingbaseESV8R6C7

test=# \d test
                Table "public.test"
 Column |  Type   | Collation | Nullable | Default
--------+---------+-----------+----------+---------
 id     | integer |           |          |
 name   | text    |           |          |
Indexes:
    "test_id" btree (id)
    "test_name" btree (name)

insert into test select generate_series(1,1000000), generate_series(1,1000000)||'tt';

test=# select count(*) from test;
  count
----------
 1000000
(1 row)


执行计划没走索引
test=# explain analyze select * from test where name like '99999%';
                                                     QUERY PLAN
---------------------------------------------------------------------------------------------------------------------
 Gather  (cost=1000.00..11653.33 rows=100 width=12) (actual time=0.261..75.993 rows=11 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   ->  Parallel Seq Scan on test  (cost=0.00..10643.33 rows=42 width=12) (actual time=30.369..55.302 rows=4 loops=3)
         Filter: (name ~~ '99999%'::text)
         Rows Removed by Filter: 333330
 Planning Time: 0.051 ms
 Execution Time: 76.046 ms
(8 rows)


--关闭全表扫后,执行计划仍不走索引
test=# set enable_seqscan = off;
SET
test=# explain analyze select * from test where name like '99999%';
                                                      QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
 Seq Scan on test  (cost=10000000000.00..10000017935.00 rows=100 width=12) (actual time=0.133..67.511 rows=11 loops=1)
   Filter: (name ~~ '99999%'::text)
   Rows Removed by Filter: 999989
 Planning Time: 0.077 ms
 Execution Time: 67.552 ms
(5 rows)




在KingbaseES数据库中的特性:只有在数据库 Collate 为 C 时,like 使用后缀通配符(%)时,才会用到索引。

如下所示,test库,上述为 Collate 为 zh_CN.UTF-8 时的示例,
test=# \l
                               List of databases
   Name    | Owner  | Encoding |   Collate   |    Ctype    | Access privileges
-----------+--------+----------+-------------+-------------+-------------------
 security  | system | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 |
 template0 | system | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/system        +
           |        |          |             |             | system=CTc/system
 template1 | system | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/system        +
           |        |          |             |             | system=CTc/system
 test      | system | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 | =Tc/system       +
           |        |          |             |             | system=CTc/system+
           |        |          |             |             | u1=c/system      +
           |        |          |             |             | u2=c/system

(6 rows)


下面看下Collation为 C 时的测试示例

alter table test alter name type text COLLATE "c";

test=# \d test
                Table "public.test"
 Column |  Type   | Collation | Nullable | Default
--------+---------+-----------+----------+---------
 id     | integer |           |          |
 name   | text    | c         |          |
Indexes:
    "test_id" btree (id)
    "test_name" btree (name)


执行计划走索引
test=# explain analyze select * from test where name like '99999%';
                                                       QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on test  (cost=127.67..5733.52 rows=5000 width=36) (actual time=0.018..0.022 rows=11 loops=1)
   Filter: (name ~~ '99999%'::text)
   Heap Blocks: exact=2
   ->  Bitmap Index Scan on test_name  (cost=0.00..126.42 rows=5000 width=0) (actual time=0.011..0.011 rows=11 loops=1)
         Index Cond: ((name >= '99999'::text) AND (name < '9999:'::text))
 Planning Time: 0.183 ms
 Execution Time: 0.037 ms
(7 rows)
以上是通过修改表列的排序规则实现该列的索引的使用,还可以通过创建数据库时指定排序规则,或者创建表时指定排序规则。
参考博客园文档:https://www.cnblogs.com/kingbase/p/16743713.html



测试另一种方式:
1) 创建索引时,加上对应字段类型的操作符
--重建索引
test=# \d test
                Table "public.test"
 Column |  Type   | Collation | Nullable | Default
--------+---------+-----------+----------+---------
 id     | integer |           |          |
 name   | text    | en_US     |          |
Indexes:
    "test_id" btree (id)
    "test_name" btree (name)


test=# drop index test_name;
DROP INDEX
test=# create index test_name on test(name varchar_pattern_ops);
CREATE INDEX
test=# \d test
                Table "public.test"
 Column |  Type   | Collation | Nullable | Default
--------+---------+-----------+----------+---------
 id     | integer |           |          |
 name   | text    | en_US     |          |
Indexes:
    "test_id" btree (id)
    "test_name" btree (name varchar_pattern_ops)



执行计划可以走索引
test=#  explain analyze select * from test where name like '99999%';
                                                       QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on test  (cost=127.67..5733.52 rows=5000 width=36) (actual time=0.018..0.022 rows=11 loops=1)
   Filter: (name ~~ '99999%'::text)
   Heap Blocks: exact=2
   ->  Bitmap Index Scan on test_name  (cost=0.00..126.42 rows=5000 width=0) (actual time=0.011..0.011 rows=11 loops=1)
         Index Cond: ((name ~>=~ '99999'::text) AND (name ~<~ '9999:'::text))
 Planning Time: 0.218 ms
 Execution Time: 0.037 ms
(7 rows)

操作符text_pattern_ops、varchar_pattern_ops、bpchar_pattern_ops 分别支持类型 text、varchar 和 char 上的B树索引。
它们与默认操作符类的区别是值的比较是严格按照字符进行而不是根据其他相关的排序规则。
这使得这些操作符类适合于当一个数据库没有使用标准“C”区域时被使用在涉及模式匹配表达式(LIKE 或 POSIX 正则表达式)的查询中。




2)另一种创建索引方式:创建索引时指定排序规则
test=# drop index test_name;
DROP INDEX
test=# create index test_name on test(name collate "c");
CREATE INDEX
test=# \d test
                Table "public.test"
 Column |  Type   | Collation | Nullable | Default
--------+---------+-----------+----------+---------
 id     | integer |           |          |
 name   | text    | en_US     |          |
Indexes:
    "test_id" btree (id)
    "test_name" btree (name COLLATE c)

执行计划也可以走索引
test=#  explain analyze select * from test where name like '99999%';
                                                       QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on test  (cost=127.67..5733.52 rows=5000 width=36) (actual time=0.020..0.024 rows=11 loops=1)
   Filter: (name ~~ '99999%'::text)
   Heap Blocks: exact=2
   ->  Bitmap Index Scan on test_name  (cost=0.00..126.42 rows=5000 width=0) (actual time=0.012..0.013 rows=11 loops=1)
         Index Cond: ((name >= '99999'::text) AND (name < '9999:'::text))
 Planning Time: 0.153 ms
 Execution Time: 0.051 ms
(7 rows)


3)正则表达式写法走索引
test=# \d test
                Table "public.test"
 Column |  Type   | Collation | Nullable | Default
--------+---------+-----------+----------+---------
 id     | integer |           |          |
 name   | text    | en_US     |          |
Indexes:
    "test_id" btree (id)
    "test_name" btree (name)


test=# explain analyze select * from test where name like '^99999';
                                                      QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on test  (cost=115.17..5721.02 rows=5000 width=36) (actual time=0.033..0.033 rows=0 loops=1)
   Filter: (name ~~ '^99999'::text)
   ->  Bitmap Index Scan on test_name  (cost=0.00..113.92 rows=5000 width=0) (actual time=0.031..0.031 rows=0 loops=1)
         Index Cond: (name = '^99999'::text)
 Planning Time: 0.088 ms
 Execution Time: 0.048 ms
(6 rows)

总结

遇到like通配符,执行计划显示不走索引的情况,首先查看索引列,表,数据库对应的排序规则Collation,然后根据以上测试示例进行现场实测并变更排序规则。

相关文档:https://www.cnblogs.com/kingbase/p/16743713.html

标签:语句,rows,like,..,text,system,test,KingbaseES,name
From: https://www.cnblogs.com/kingbase/p/17253131.html

相关文章

  • KingbaseES V8R3 集群运维系列 -- sync_flag参数配置
    ​案例说明:在KingbaseESV8R3集群一主二备的架构中,配置了流复制为同步(sync)模式,但是集群启动后,流复制状态中显示备库是async模式(备库和主库数据已经同步),从备库的recovery.log日志也可以看到,备库启动后被复制模式设置为async模式。如下图备库recovery.log:适用版本:KingbaseES......
  • KingbaseES 分区表修改字段类型
    KingbaseES普通表修改表结构请参考:KingbaseES变更表结构表重写问题数据类型转换重写与不重写:varchar(x)转换到varchar(y)当y>=x,不需要重写。numeric(x,z)转换到numeric(y,z)当y>=x,或者不指定精度类型,不需要重写。numeric(x,c)转换到numeric(y,z)当y=xc>z,当numer......
  • KingbaseES 使用sys_bulkload远程导入
    前言sys_bulkload常见场景是本地导入数据,也可以在远程运行sys_bulkload,对数据库上的CSV文件进行导入。远程导入数据时候需要注意,csv文件和ctl文件所在服务器。以下举例展示整个远程导入的过程。测试环境V8R6C7演示目的将数据从IP2所在服务器导入到IP3远程服务器上。IP3......
  • KingbaseES 复制冲突之锁类型冲突
    背景昨天遇到客户现场的一个有关复制冲突的问题备库报错:ERROR:cancelingstatementduetoconflictwithrecovery,userwasholdingarelationlockfortoolong现场情景是备库执行逻辑备份过程中出现的报错,逻辑备份相当于备库查询语句,snapshot,这时主库业务繁忙,对备库查询......
  • KingbaseES V8R6 等待事件之LWLock Buffer_IO
    等待事件含义当进程同时尝试访问相同页面时,等待其他进程完成其输入/输出(I/O)操作时,会发生LWLock:BufferIO等待事件。其目的是将同一页读取到共享缓冲区中。每个共享缓冲区都有一个与LWLock:BufferIO等待事件相关联的I/O锁,每次都必须在共享缓冲区外部检索页。此锁用于处理多个会......
  • KingbaseES V8R3 集群运维系列 -- failover切换后集群自动恢复
    ​案例说明:KingbaseESV8R3集群默认在触发failover切换后,为保证数据安全,原主库需要通过人工介入后,恢复为新的备库加入到集群。在无人值守的现场环境,需要在触发failover切换后,主库可以自动恢复为新备考加入集群,提升架构的高可用性。适用版本:KingbaseESV8R3集群架构:node_id......
  • SQL语句(未完结)
    SQL语句标签:MySQLSQL通用语法分号结尾大小写不敏感注释:单行:--或##(MySQL方言)多行:/**/分类DDL:datadefinitionlanguage,数据定义语言,定义数据库对象:数据库、表、字段DML:datamanipulationlanguage,数据操作语言,增删改DQL:dataquerylanguage,数据查询语言,查DC......
  • 工作中,我们经常用到哪些SQL语句呢
     工作中我们基本上每天都要与数据库打交道,数据库的知识点呢也特别多,全部记住呢也是不可能的,也没必要把所有的记住(有些语句命令可能我们一辈子都用不到)。所以呢在工作之余,把工作中经常用到的一些语句整理出来,忘记的时候可以当做字典来查。个人在工作中用Oracle......
  • SQL语句练习
    --1、查询所有的课程的名称以及对应的任课老师姓名SELECTcourse.teacher_id,course.cname,teacher.tnameFROMcourseLEFTJOINteacherONcourse.teacher_id=teacher.tid;--2、查询学生表中男生有多少人SELECTstudent.gender,count(student.gender)FROMstudentWHERE......
  • 学习笔记:MySQL常用的一些SQL语句
    本文谈谈MySQL的开发必会的sql语句创建数据库createdatabasedb1;删除数据库dropdatabasedb1;创建数据表createtabletb1用户表(idintnotnullauto_increment primarykey,namechar(10),                     department_idint,            ......