KingbaseES 语句like前匹配如何使用索引
前言
有现场同事反馈 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前匹配如何使用索引的更多相关文章
- like语句百分号前置会使用到索引吗?
like语句百分号前置会使用到索引吗? 前几天看了这篇文章:谈SQL Server对like '%关键词%' 处理时的索引利用问题 看完了之后,我很想知道这篇文章是不是临时工写的?还是网站的主人写的, ...
- 面试题--如何防止sql注入,使用PreparedStatement的预编译,传入的内容就不会和原来的语句发生任何匹配的关系,达到防止注入的方法
PreparedStatement的用法 jdbc(java database connectivity,java数据库连接)的api中的主要的四个类之一的java.sql.statement要求开发 ...
- 两个字符串,s1 包含 s2,包含多次,返回每一个匹配到的索引---python
#两个字符串,s1 包含 s2,包含多次,返回每一个匹配到的索引 def findSubIndex(str1,subStr): str_len = len(str1) sub_len = len(su ...
- sql语句中like匹配的用法详解
在SQL结构化查询语言中,LIKE语句有着至关重要的作用. LIKE语句的语法格式是:select * from 表名 where 字段名 like 对应值(子串),它主要是针对字符型字段的,它的作用 ...
- 【转】同一个SQL查询语句,为什么使用到的索引不同?
问: 同一个SQL查询语句,只是修改where条件中的一个值,为什么使用到的索引情况也会不同?谢谢! 1) explain执行结果,如下图: 2) 表中的数据如下图: 3) 表结构如下图: 4) 创建 ...
- uploadPreview 上传图片前预览 IE9 索引无效的问题
最近公司的项目用到比较多的上传图片的操作,所以用到了基于jquery的上传前预览的插件 uploadPreview ,后来测试的时候发现在IE9下报索引无效的问题. 异常的产生方式 放一个file控件 ...
- finall语句是在return语句执行前被执行还是执行后被执行?
finally对try...catch的影响和执行时间 一.finally语句不被执行的两种情况 我们在学习抛出异常的时候学习到了finally语句块,这个语句块一般会被执行,但是有两种情况下不被执行 ...
- 数据库char varchar nchar nvarchar,编码Unicode,UTF8,GBK等,Sql语句中文前为什么加N(一次线上数据存储乱码排查)
背景 公司有一个数据处理线,上面的数据经过不同环境处理,然后上线到正式库.其中一个环节需要将数据进行处理然后导入到另外一个库(Sql Server).这个处理的程序是老大用python写的,处理完后进 ...
- Java开发学习(四十五)----MyBatisPlus查询语句之映射匹配兼容性
1.映射匹配兼容性 我们已经能从表中查询出数据,并将数据封装到模型类中,这整个过程涉及到一张表和一个模型类: 之所以数据能够成功的从表中获取并封装到模型对象中,原因是表的字段列名和模型类的属性名一样. ...
- mysql语句插入前判断数据是否重复
在mysql中插入数据有时需要判断数据插入是否重复 语句编写:insert into 表(相应字段) select 相应字段 from dual where not exists (select 相应 ...
随机推荐
- Spring Boot整合JWT实现接口访问认证
最近项目组需要对外开发相关API接口,需要对外系统进行授权认证.实现流程是先给第三方系统分配appId和appSecret,第三方系统调用我getToken接口获取token,然后将token填入Au ...
- CentOS8安装Docker报错问题解决
问题描述 CentOS版本:8.5.2111. # cat /etc/redhat-release CentOS Linux release 8.5.2111 安装准备: # 安装所需软件包 sudo ...
- django学习第十三天--自定义中间件
jquery操作cookie 下载地址 http://plugins.jquery.com/cookie/ 引入 <script type="text/javascript" ...
- 修改centos7虚拟机的用户密码
在忘记原密码无法登录桌面的情况下,修改centos7的用户密码 非常规启动,进入编辑启动菜单 在启动GRUB菜单中选择编辑选项,按键e进入编辑; 找到linux16开头的一行,在该行中寻找ro的所在地 ...
- 【Azure 事件中心】 Event Grid(事件网格)+Azure Functions处理IOT Hub中的消息
问题描述 使用IOT Hub的Events功能,使用Event Grid(事件网格)订阅IOTHub状态消息,发送到Azure Functions.那如何来创建Event Grid触发的Functio ...
- ui转py文件
ui文件转py文件并且使用 简单做一个笔记,以后忘了回来看看 转换 在QT Designer中创建完ui文件后,回到pycharm中,右键点击ui文件,选择pyuic 完成后获得了和ui文件同名的py ...
- Codeforces Round 924 (Div. 2)B. Equalize(思维+双指针)
目录 题面 链接 题意 题解 代码 题面 链接 B. Equalize 题意 给一个数组\(a\),然后让你给这个数组加上一个排列,求出现最多的次数 题解 赛时没过不应该. 最开始很容易想到要去重,因 ...
- Docker 安装成功(win10家庭版)
https://desktop.docker.com/win/stable/Docker Desktop Installer.exe 安装遇到了 然后 更新 这个 https://wslstorest ...
- Windows改变终端字体后,终端一片黑 的解决办法
使用Windows终端的时候总觉得字体不好看,于是乎按照网上的教程改了一下 注册表 计算机\HKEY_CURRENT_USER\Console%SystemRoot%_system32_cmd.exe ...
- 音频信号质量的度量标准--MOS得分的由来
早期语音质量的评价方式是凭主观的,人们在打通电话之后通过人耳来感知语音质量的好坏.1996年国际ITU组织在ITU-T P.800和P.830建议书开始制订相关的评测标准:MOS(Mean Opini ...