SqlServer之like、charindex、patindex

本文通过实验对比了SQL Server中like、charindex、patindex三种查询方式在不同条件下的性能表现,结果显示在特定情况下patindex的性能最优。

SqlServer之like、charindex、patindex


1、环境介绍
测试环境 SQL2005
测试数据 200W条


2、环境准备
2.1建表
CREATE TABLE [dbo].[Depratments](
[Dep_id] [int] NOT NULL,
[Dep_name] [varchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL
) ON [PRIMARY]
2.2创建数据
create procedure ins_Depratments
as
declare @n int;
declare @title varchar(30);
set @n =1;
set @title='';
begin
while @n<2000000
begin
-- set @title = (select case when (cast(floor(rand() * 6) as int)) =5 then '部门经理' else '职员'end);
insert into Depratments (Dep_id,Dep_name) values (@n,'开发'+CAST(@n as varchar)) ;
-- insert into employees values (@n,'刘备'+CAST(@n as varchar),'男',@title,
78000,'11110333x'+CAST(@n as varchar),@n,getdate());
set @n=@n+1;
end
end
2.3执行 exec ins_Depratments

3、场景
3.1前后都有百分号的查询
SET STATISTICS IO ON
set statistics time ON
go
select count(*) from depratments where Dep_name like '%开发1000%';
go
select count(*) from depratments where charindex('开发1000',Dep_name)>0;
go
select count(*) from depratments where patindex('%开发1000%',Dep_name)>0;
go
无索引的情况 charindex > patindex > like
CPU 时间 = 4391 毫秒,占用时间 = 5322 毫秒。
CPU 时间 = 3812 毫秒,占用时间 = 4690 毫秒。
CPU 时间 = 4047 毫秒,占用时间 = 5124 毫秒。
带索引的情况 charindex > patindex > like
CPU 时间 = 4297 毫秒,占用时间 = 4535 毫秒。
CPU 时间 = 3844 毫秒,占用时间 = 4024 毫秒。
CPU 时间 = 4219 毫秒,占用时间 = 4351 毫秒。
结论:
当前后都使用百分号的情况(%string%),①charindex性能稍微好点,like、patindex性能相近;②索引在这种情况中失效

3.2百分号在后面的查询
SET STATISTICS IO ON
set statistics time ON
go
select count(*) from depratments where Dep_name like '开发1000%';
go
select count(*) from depratments where charindex('开发1000',Dep_name)>0;
go
select count(*) from depratments where patindex('开发1000%',Dep_name)>0;
go

无索引的情况 patindex > like > charindex
CPU 时间 = 844 毫秒,占用时间 = 1465 毫秒。
CPU 时间 = 3875 毫秒,占用时间 = 3914 毫秒。
CPU 时间 = 968 毫秒,占用时间 = 969 毫秒。

带索引的情况  like > patindex > charindex
CPU 时间 = 0 毫秒,占用时间 = 18 毫秒
CPU 时间 = 3766 毫秒,占用时间 = 4026 毫秒。
CPU 时间 = 937 毫秒,占用时间 = 983 毫秒。
结论:
无索引的情况,patindex的性能最佳,是charindex性能的4倍
带索引的情况,like的性能最佳

总结:
①索引只适用于百分号在后面的情况(string%)
②在前后都是百分号的情况下charindex 的性能最佳
③百分号在后面的查询,无索引的情况,patindex的性能最佳

<think> 首先,用户的问题是基于提供的参考文献,特别是关于SQL Server中LIKE查询慢的解决办法。参考了三个引用: - 引用[1]: 讨论了LIKE查询慢的原因,如使用LIKE '%a%'时不使用索引,建议使用全文索引或避免CHAR类型。 - 引用[2]: 描述了SQL Server中LIKE运算符的语法和通配符,包括使用通配符的方式。 - 引用[3]: 提到在MySQL中使用instr函数代替LIKE来加快查询,但这是在MySQL中,不是SQL Server。 用户明确说:“我想查找在SQL Server中解决LIKE查询慢的问题的解决方案”,所以我的回答应该专注于SQL Server。 系统指令要求: - 所有行内数学表达式使用$...$格式。(在这个上下文中,可能不涉及数学表达式,但如果有变量或类似的东西,需要格式化。) - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。(可能不适用,除非有公式。) - 使用中文回答。 - 生成相关问题。(在回答末尾添加相关问题。) - 引用的段落末尾自然地添加引用标识,如[^1]。 用户上一次的问题是关于LIKE查询慢的解决办法,所以我需要基于参考的内容构建回答。 关键点从引用中提取: - 引用[1]:LIKE查询慢,尤其是LIKE '%a%',因为不使用索引;建议使用全文索引或VARCHAR类型。 - 引用[2]:LIKE语法和通配符;没有直接提到优化。 - 引用[3]:在MySQL中用instr代替LIKE,但在SQL Server中不直接适用。 SQL Server的具体优化: - 避免前导通配符:如LIKE 'a%'可以使用索引,但LIKE '%a'或LIKE '%a%'不能。 - 使用全文索引处理文本搜索。 - 数据类型:使用VARCHAR而不是CHAR,因为CHAR是固定长度。 - 其他优化:如减少查询字段、使用覆盖索引等。 结构化回答: 1. **介绍问题**:解释为什么LIKE查询慢,基于引用[1]。 2. **优化方案**: - 避免使用前导通配符(如%开头)。 - 使用全文索引(Full-Text Search)。 - 选择合适的字符串类型(VARCHAR vs CHAR)。 - 使用其他函数或方法,如PATINDEX或CONTAINS(SQL Server有全文搜索功能)。 - 索引优化:确保列有索引,但只有特定模式能用索引。 3. **引用处理**:在相关部分添加引用标识。 4. **生成相关问题**:在回答末尾添加几个相关问题。 使用中文回答。 步骤: - 开头:介绍SQL Server中LIKE查询慢的原因。 - 主体:列出具体解决办法。 - 结尾:总结建议。 - 添加相关问题。 确保回答真实可靠:基于SQL Server最佳实践。 可能的解决办法: 1. **优化查询模式**:避免LIKE '%text%',尽量用LIKE 'text%'。[^1] 2. **使用全文索引**:对于大量文本搜索,创建全文索引来提高性能。[^1] 3. **数据类型优化**:使用VARCHAR而不是CHAR,以避免不必要的空格填充。[^1] 4. **函数替代**:在SQL Server中,可以考虑使用CONTAINS或FREETEXT函数,这是全文搜索的一部分。[引用标准知识] 5. **索引使用**:只在能用索引的模式下使用索引。 6. **查询优化**:只选择必要的列,而不是SELECT *。 7. **避免在LIKE中使用函数**:如LIKE UPPER(column),这会让索引失效。 最后,生成相关问题,如: - 如何创建和使用SQL Server全文索引? - 什么是SQL Server中替代LIKE查询的其他方法? - 如何优化数据库结构来提高LIKE查询性能? </think> ### SQL Server中LIKE查询慢的解决办法 在SQL Server中,使用LIKE运算符进行模糊查询时,性能问题常见于模式如`LIKE '%a%'`或`LIKE '%a'`,因为这些查询往往无法有效利用索引,导致全表扫描和数据读取量增加,从而显著降低查询速度[^1]。以下是基于SQL Server最佳实践的优化方案,结合引用内容与实际经验,分为几个关键步骤进行说明。这些方法旨在减少查询耗时,提高效率。 #### 1. **优化查询模式,避免低效通配符** - **问题分析**:LIKE查询的性能高度依赖于通配符的位置。例如,`LIKE 'a%'`(后缀模糊)可以使用索引,因为它匹配以“a”开头的字符串;而`LIKE '%a'`(前缀模糊)或`LIKE '%a%'`(全模糊)则无法利用索引,因为SQL Server无法预先确定起始点,导致全表扫描[^1][^2]。 - **解决方案**: - 优先使用可索引的模式,如`LIKE 'a%'`。如果必须使用全模糊查询,尝试结合其他条件(如日期范围)缩小数据集。 - 使用通配符时,遵循SQL Server的通配符规则:百分比符(`%`)匹配任意字符序列,下划线(`_`)匹配单个字符,避免过度使用`[list]`或`[^]`通配符,除非必要,因为这些也可能降低性能[^2]。 - **示例查询**:将低效的`SELECT * FROM table WHERE column LIKE '%search%'`优化为`SELECT column FROM table WHERE column LIKE 'search%'`,并在`column`上创建索引[^1]。 #### 2. **使用全文索引替代LIKE** - **问题分析**:对于包含大量文本的列(如文章内容或长描述),LIKE查询会随着字符串长度增加而变慢,尤其是当字段类型为CHAR时(固定长度字符串可能包含多余空格,增加比较开销)[^1]。全文索引(Full-Text Search)是SQL Server内置功能,专门为文本搜索设计,支持快速模糊匹配。 - **解决方案**: - **创建全文索引**:在目标列上启用全文索引。这需要额外存储空间,但显著提升性能。例如: ```sql -- 创建全文目录和索引 CREATE FULLTEXT CATALOG ft_catalog AS DEFAULT; CREATE FULLTEXT INDEX ON dbo.table(column) KEY INDEX pk_index WITH STOPLIST = SYSTEM; ``` 然后使用`CONTAINS`或`FREETEXT`函数替代LIKE,如:`SELECT * FROM table WHERE CONTAINS(column, '"search*"')`(支持前缀匹配和词根搜索)[^1]。 - **数据类型优化**:将列类型从CHAR改为VARCHAR,减少长度固定带来的冗余。VARCHAR动态分配空间,降低比较开销[^1]。 #### 3. **使用函数或替代方法减少全表扫描** - **问题分析**:LIKE查询在无法使用索引时会引起全表扫描,拖慢性能。引用[^3]提到在MySQL中使用`instr()`函数优化,但在SQL Server中,类似函数如`CHARINDEX`或`PATINDEX`可作为替代,减少部分开销。 - **解决方案**: - **使用CHARINDEXPATINDEX**:这些函数在特定场景下更快,因为它们返回匹配位置而非布尔值,便于结合索引。例如: ```sql SELECT * FROM table WHERE CHARINDEX('search', column) > 0; ``` 但注意:函数调用本身可能让索引失效,因此仅在列已索引且查询模式简单时使用。 - **结合覆盖索引**:创建覆盖索引(Covering Index),包含查询涉及的列,避免访问表数据。例如:`CREATE INDEX idx_covering ON table(column) INCLUDE (other_columns)`,然后配合`SELECT column FROM table WHERE column LIKE 'a%'`[^1]。 - **减少返回字段**:避免`SELECT *`,指定必要列以减少数据传输量。 #### 4. **其他优化技巧** - **索引策略**:为列创建标准索引(如B-tree索引),但仅对`LIKE 'a%'`有效。对于频繁的模糊查询,定期重建索引(使用`ALTER INDEX REBUILD`)维护性能[^1]。 - **查询重写**:将复杂LIKE拆分为多个OR条件或使用临时表。例如:`WHERE column LIKE 'a%' OR column LIKE '%b'`,但需测试性能影响。 - **服务器级优化**:增加内存、优化统计信息(使用`UPDATE STATISTICS`),或在查询中添加提示如`OPTION (FAST n)`限制返回行数。 - **避免大小写敏感问题**:LIKE默认不区分大小写,但如果数据库设置为区分大小写,可使用`COLLATE`子句统一比较规则,避免意外开销[^2]。 #### 总结建议 优化LIKE查询的核心是**避免前导通配符、优先使用全文索引或VARCHAR类型,并结合索引和函数替代**。实际场景中,测试不同方案(如先用少量数据验证)至关重要。如果查询涉及海量数据,考虑归档旧数据或使用分区表。根据引用[^1][^2],这些方法已在实践中证明有效,能显著提升SQL Server的模糊查询速度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值