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和Spring Boot的区别
spring Spring 是一个开源轻量级框架,它允许 Java EE 7 开发人员构建简单.可靠和可扩展的企业应用程序.该框架主要侧重于提供各种方法来帮助您管理业务对象.与 Java 数据库连接 ...
- Redis搭建Sentinel实验环境
环境准备 在物理机上启动3台虚拟机,IP地址分别为:192.168.56.4,192.168.56.5,192.168.56.6. 1.确保3台虚拟机的网络是相互联通的. 2.确保已经在3台虚拟机上安 ...
- 关于Image的mode属性(多图示例)
一.总览 Image的mode是指图片裁剪.缩放的模式,共有14个合法值,分别是: /** 缩放模式,不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素 */ scaleToFill ...
- Java JVM——7.本地方法栈
本地方法栈 Java虚拟机栈于管理Java方法的调用,而本地方法栈用于管理本地方法的调用. 本地方法栈,也是线程私有的. 允许被实现成固定或者是可动态扩展的内存大小.(在内存溢出方面是相同的) ✎ 如 ...
- Gin框架使用jwt-go配合中间件认证
参考文档 // 文档 https://github.com/golang-jwt/jwt https://pkg.go.dev/github.com/golang-jwt/jwt@v3.2.2+inc ...
- 【Azure 事件中心】使用Kafka的性能测试工具(kafka-producer-perf-test)测试生产者发送消息到Azure Event Hub的性能
问题描述 Azure Event Hub支持 kafka,所以为了测试消息生产者所在环境与Azure Event Hub之间发送消息的性能如何,特别使用 kafka 官方测试生产者,消费者的性能工具 ...
- 了解 Docker 网络
本章将会简单地讲述 Docker 中的网络,对于 CNM.Libnetwork 这些,限于笔者个人水平,将不会包含在内. Docker 的四种网络模式 Docker 有 bridge.none.hos ...
- .Net下的简易Http请求调用(Post与Get)
http请求调用是开发中经常会用到的功能.在内,调用自有项目的Web Api等形式接口时会用到:在外,调用一些第三方功能接口时,也会用到,因为,这些第三方功能往往是通过http地址的形式提供的,比如: ...
- 在Java中如何优雅的停止一个线程?可别再用Thread.stop()了!
写在开头 经过上几篇博文的学习,我们知道在Java中可以通过new Thread().start()创建一个线程,那今天我们就来思考另外一个问题:线程的终止 自然终止有两种情况: 1. 线程的任务执行 ...
- 使用pymysql库,将tushare股票信息保存入本地MySQL数据库
使用pymysql库,将tushare股票信息保存入本地MySQL数据库 1.前言 由于tushare存在积分权限限制,高频读取tushare数据容易挤占服务器带宽,因此对于常用的tushare数据, ...