前言

有现场同事反馈 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

KingbaseES 语句like前匹配如何使用索引的更多相关文章

  1. like语句百分号前置会使用到索引吗?

    like语句百分号前置会使用到索引吗? 前几天看了这篇文章:谈SQL Server对like '%关键词%' 处理时的索引利用问题 看完了之后,我很想知道这篇文章是不是临时工写的?还是网站的主人写的, ...

  2. 面试题--如何防止sql注入,使用PreparedStatement的预编译,传入的内容就不会和原来的语句发生任何匹配的关系,达到防止注入的方法

    PreparedStatement的用法 jdbc(java database connectivity,java数据库连接)的api中的主要的四个类之一的java.sql.statement要求开发 ...

  3. 两个字符串,s1 包含 s2,包含多次,返回每一个匹配到的索引---python

    #两个字符串,s1 包含 s2,包含多次,返回每一个匹配到的索引 def findSubIndex(str1,subStr): str_len = len(str1) sub_len = len(su ...

  4. sql语句中like匹配的用法详解

    在SQL结构化查询语言中,LIKE语句有着至关重要的作用. LIKE语句的语法格式是:select * from 表名 where 字段名 like 对应值(子串),它主要是针对字符型字段的,它的作用 ...

  5. 【转】同一个SQL查询语句,为什么使用到的索引不同?

    问: 同一个SQL查询语句,只是修改where条件中的一个值,为什么使用到的索引情况也会不同?谢谢! 1) explain执行结果,如下图: 2) 表中的数据如下图: 3) 表结构如下图: 4) 创建 ...

  6. uploadPreview 上传图片前预览 IE9 索引无效的问题

    最近公司的项目用到比较多的上传图片的操作,所以用到了基于jquery的上传前预览的插件 uploadPreview ,后来测试的时候发现在IE9下报索引无效的问题. 异常的产生方式 放一个file控件 ...

  7. finall语句是在return语句执行前被执行还是执行后被执行?

    finally对try...catch的影响和执行时间 一.finally语句不被执行的两种情况 我们在学习抛出异常的时候学习到了finally语句块,这个语句块一般会被执行,但是有两种情况下不被执行 ...

  8. 数据库char varchar nchar nvarchar,编码Unicode,UTF8,GBK等,Sql语句中文前为什么加N(一次线上数据存储乱码排查)

    背景 公司有一个数据处理线,上面的数据经过不同环境处理,然后上线到正式库.其中一个环节需要将数据进行处理然后导入到另外一个库(Sql Server).这个处理的程序是老大用python写的,处理完后进 ...

  9. Java开发学习(四十五)----MyBatisPlus查询语句之映射匹配兼容性

    1.映射匹配兼容性 我们已经能从表中查询出数据,并将数据封装到模型类中,这整个过程涉及到一张表和一个模型类: 之所以数据能够成功的从表中获取并封装到模型对象中,原因是表的字段列名和模型类的属性名一样. ...

  10. mysql语句插入前判断数据是否重复

    在mysql中插入数据有时需要判断数据插入是否重复 语句编写:insert into 表(相应字段) select 相应字段 from dual where not exists (select 相应 ...

随机推荐

  1. 【OpenGL ES】EGL+FBO离屏渲染

    1 前言 ​ FBO离屏渲染 中使用 GLSurfaceView 来驱动 Renderer 渲染图片,为了隐藏 GLSurfaceView,将其设置为透明的,并且宽高都设置为1.本文将使用 EGL 代 ...

  2. 将docker镜像推送到阿里云镜像仓库

    1.注册阿里云账号(支付宝扫码登录也可以) 进入控制台,找到[容器镜像服务] 2.创建命名空间 3.创建镜像仓库 4.设置授权凭证 5.登录 docker login --username=index ...

  3. 如何基于three.js(webgl)引擎架构,实现3D密集架库房,3D档案室(3d机器人取档、机器人盘点、人工查档、设备巡检)

     前言: 这是最好的时代,也是最坏的时代:是充满挑战的时代,也是充满机遇的时代.是科技飞速的时代,也是无限可能的时代. 近年来,人工智能(AI)技术的飞速发展已经席卷了全球,不断突破着技术边界,为各行 ...

  4. time模块,os操作系统及os模块和shutil模块用法---day16

    1.时间模块 import time time.time() 获取本地时间戳 localtime() 获取本地时间元组,参数是时间戳,默认不写是当前 ***** mktime() 通过时间元组获取时间 ...

  5. django学习第四天----mark_safe的用法,静态文件配置,用指令创建django项目应用注意点,ORM介绍,创建表执行命令,模板渲染补充(组件),inclusion_tag 自定义标签

    补充第三天跟safe差不多的一个方法 templatetags文件夹 自定义的py文件 需要先导入模块 from django.utils.safestring import mark_safe @r ...

  6. 记一次酣畅淋漓的 K8s Ingress 排错过程(302,404,503,...)

    故事开始 第 1 关:[流量重定向到 /] 第 2 关:[应用返回 302,重定向到 /,引入 503 错误] 第 3 关:[静态资源访问遇到 503 问题] 第 4 关:[静态资源访问遇到 403 ...

  7. 【Azure Batch】在中国区批处理服务(Mooncake Batch Account)上实验自动池(Auto Pool)的创建/删除

    问题描述 在Azure Batch的介绍文档中,提出了自动池的概念, 它可以在任务完成后,自动删除Pool资源,详细介绍:https://docs.azure.cn/zh-cn/batch/nodes ...

  8. 【Azure Redis 缓存】VM 里的 Redis 能直接迁移到 Azure Cache for Redis ? 需要改动代码吗?

    问题描述 原来部署在VM 里的 Redis 能直接迁移到 Azure Cache for Redis? 需要改动代码吗? 问题解答 以上问题需要从两个方面来解答. 第一:VM中Redis的数据转移到 ...

  9. MongoDB下载和可视化工具NoSQL Manager for MongoDB 软件的下载,连接数据库

    在官网下载MongoDB的版本为4.0.28,之前试了好几个高版本和低版本,都不行,最后,4.0.28版本好了.下载网页:https://www.mongodb.com/try/download/co ...

  10. 8、mysql的内存管理及优化

    内存优化原则 1) 将尽量多的内存分配给MySQL做缓存,但要给操作系统和其他程序预留足够内存. 2) MyISAM 存储引擎的数据文件读取依赖于操作系统自身的IO缓存,因此,如果有MyISAM表,就 ...