谈谈SQL数据库中滥用临时表、排序的解决方案优化(举例:汉字转拼音函数)...

本文介绍了一种在SQLServer中实现智能搜索的方法,利用自定义函数将汉字转换为拼音首字母,以支持按拼音首字母排序的搜索需求,并对比了几种不同函数实现的性能。

游标、临时表、触发器、COLLATE等等……
无可厚非、这些都是好东西,我为什么今天要花时间来写这些东西呢?
是因为我发现慢慢的很多人用久了这些东西之后会形成一种习惯,不管解决什么问题动不动都会把它们搬出来,由此我看到了很多漂亮的代码在性能效率面前却显得不那么优秀。

好了废话不多说开始进入正题吧。


今天的案例

场景:

需要通过用户输入的姓名关键字来搜索用户。用户输入关键字'x'来搜索用户(数据来源于表[Name字段中]或内存[List<UserInfo>]中)

要求:

得到的结果排序应为:

x

xia

xiao

yx

即:

  1. 包含x字母的结果均应显示出来
  2. 首字母匹配的结果应该排在前面(如x开头)
  3. 在条件2相同的前提下更短的结果应排在前面(如x排在xia前面)
各位大侠能否给出一套C#与SQL Server(2008)的解决方案?


补充:

如果能一起解决中文问题最好,如搜索'x'

得到的结果排序应为:

x

xiani

夏荣

肖小笑

杨星

即将汉字的拼音首字母纳入在内,不知SQL Server是否支持这一特性的搜索?

 

感谢[学习的脚步]这位网友提出来的问题

其实要解决这个问题不难,无非就是汉字转拼音首字母

---------------------------------------------------------------------------------------------

先给出解决方案一

---------------------准备工作 开始-------------------------------
if object_id('zhuisuos')is not null
drop table zhuisuos
go

create table zhuisuos
(
name 
varchar(100)
)
insert into zhuisuos values('追索')
insert into zhuisuos values('追索2')
insert into zhuisuos values('xia')
insert into zhuisuos values('dxc')
insert into zhuisuos values('x')
insert into zhuisuos values('xx')
insert into zhuisuos values('xiani')
insert into zhuisuos values('yx')
insert into zhuisuos values('夏荣')
insert into zhuisuos values('肖小笑')
insert into zhuisuos values('杨星')
go
-------------------------------------------------------------------------------
--
建立汉字转拼音首字母函数
if object_id('fn_getpy1')is not null
drop function fn_getpy1
go

GO
create   function   [dbo].fn_getpy1
(
@str   nvarchar(4000)) 
returns   nvarchar(4000
as 
begin 
declare   @str_len   int,@result   nvarchar(4000
declare   @zhuisuo   table
(firstspell   
nchar(1)   collate   Chinese_PRC_CI_AS,
letter   
nchar(1)) 
set @str_len=len(@str)
set @result= ' ' 
insert   into   @zhuisuo
(firstspell,letter) 
    
select   '吖 '''   union   all   select   '八 '''   union   all 
    
select   '嚓 '''   union   all   select   '咑 '''   union   all 
    
select   '妸 '''   union   all   select   '发 '''   union   all 
    
select   '旮 '''   union   all   select   '铪 '''   union   all 
    
select   '丌 '''   union   all   select   '咔 '''   union   all 
    
select   '垃 '''   union   all   select   '嘸 '''   union   all 
    
select   '拏 '''   union   all   select   '噢 '''   union   all 
    
select   '妑 '''   union   all   select   '七 '''   union   all 
    
select   '呥 '''   union   all   select   '仨 '''   union   all 
    
select   '他 '''   union   all   select   '屲 '''   union   all 
    
select   '夕 '''   union   all   select   '丫 '''   union   all 
    
select   '帀 ''' 
    
while   @str_len> 0 
    
begin 
        
select   top   1   @result=letter+@result,@str_len=@str_len-1 
            
from   @zhuisuo     
            
where   firstspell <=substring(@str,@str_len,1
            
order   by   firstspell   desc 
        
if   @@rowcount=0 
          
select   @result=substring(@str,@str_len,1)+@result,@str_len=@str_len-1 
    
end 
    
return(@result
end
---------------------准备工作 结束-------------------------------

--正式查询
declare @str varchar(10)
set @str='x'
create table #result
(name 
varchar(100null,id int null,lens int null)

insert into #result 
select name,1,len(name) from zhuisuos
where name like @str+'%'

insert into #result
select name,2,len(name) from zhuisuos
where name like '%'+@str+'%' and name not like @str+'%'

insert into #result
select name,3,len(name) from zhuisuos
where dbo.fn_getpy1 (name) like @str+'%' and name not like @str+'%' and name not like '%'+@str+'%'

insert into #result
select name,4,len(name) from zhuisuos
where dbo.fn_getpy1 (name) like '%'+@str+'%' and dbo.fn_getpy1 (name) not like @str+'%'
  
and  name not like @str+'%' and name not like '%'+@str+'%'

select name from #result
order by id,lens
drop table #result

这个解决方案已经满足查询要求

其它都不管 我们重点来看看这次写的这个函数

象这样的汉字转拼音函数在网上一搜一大把 今天我就要举例几个方案让大家对优化及开销有个清楚的概念

解决方案一写的函数实在是太糟糕了(以上及接下来举出的案例并无冒犯任何雷同及原创代码之意,还请多多包涵)

 

为什么这么说呢

这是它的执行计划

它用了临时表并且排序

表插入开销0.01  表扫描开销0.003 表排序0.011

估计总开销0.0246

实际执行:我拿1万行数据调用此函数花了我20几秒、一个查询操作你愿意等20多秒吗

所以看到这样的执行计划实在很抱歉

解决方案二

create function [dbo].[fn_getpy2](@Str varchar(500)='')
returns varchar(500)
as
begin
declare @strlen int,@return varchar(500),@ii int
declare @n int,@c char(1),@chn nchar(1)

select @strlen=len(@str),

<think>嗯,用户问的是SQL优化中的谓词下推,还提到是不是要多使用子查询。首先,我需要回忆一下谓词下推的定义和原理。谓词下推,英文是Predicate Pushdown,是SQL优化中的一种技术,主要是把过滤条件尽可能早地应用到数据源,减少后续处理的数据量,从而提高查询效率。 接下来,用户可能对子查询和谓词下推之间的关系有疑问。需要澄清的是,谓词下推并不是说要多用子查询,而是如何在现有的查询结构中,将过滤条件下推到更靠近数据源的位置,比如在子查询内部或者JOIN之前应用WHERE条件。这可能涉及到对子查询的处理,但并不是说必须使用子查询来实现。 然后,我得考虑用户为什么会将子查询和谓词下推联系起来。可能是在某些情况下,通过子查询的形式,可以手动将谓词下推到更早的阶段,但优化器通常会自动处理这些。用户可能误解了谓词下推需要依赖子查询,但实际上优化器会自动进行这类优化,无论有没有子查询。 需要举例说明,比如一个带有JOIN和WHERE的查询,优化器会把WHERE条件推到JOIN之前,减少参与JOIN的数据量。或者对于子查询中的过滤条件,如果可能的话,优化器会将其下推到子查询内部,而不是在外部处理。 还要注意,有时候手动重写查询,比如将过滤条件放在子查询内部,可能帮助优化器更好地应用谓词下推,尤其是在复杂查询或优化器不够智能的情况下。但这不是说多用子查询,而是合理使用结构让优化器更有效工作。 另外,可能需要提到不同数据库系统的实现差异,比如Hive、Spark SQL和传统关系型数据库在处理谓词下推时的不同支持程度,以及子查询是否被优化器有效处理的情况。 最后,总结谓词下推的核心是尽早过滤数据,减少中间结果集的大小,而子查询的使用与否取决于具体的查询结构和优化器的能力。正确的做法是让优化器自动处理谓词下推,必要时通过调整查询结构(可能包括子查询)来辅助优化器。</think>**谓词下推(Predicate Pushdown)** 是 SQL 优化中一种常见的技术,核心目标是**尽早过滤数据,减少后续计算的数据量**,从而提升查询性能。它的核心思想是将过滤条件(谓词)尽可能“下推”到靠近数据源的层级(例如子查询、JOIN 操作之前),而不是在最终结果集中才进行过滤。 --- ### **谓词下推的原理** 1. **减少数据流动**:在查询计划的早期阶段(如扫描表时、子查询内部、JOIN 操作前)应用过滤条件,减少需要处理的数据量。 2. **降低计算开销**:避免对无关数据进行聚合、排序、连接等昂贵操作。 --- ### **示例说明** 假设有以下 SQL(未优化): ```sql SELECT * FROM ( SELECT user_id, order_date, amount FROM orders ) AS subquery WHERE order_date >= '2023-01-01'; ``` **未优化时**:子查询会先扫描全表生成中间结果,外层再过滤 `order_date`。 **优化后(谓词下推)**:数据库会自动将 `order_date` 条件推入子查询内部,直接减少子查询的数据量: ```sql SELECT * FROM ( SELECT user_id, order_date, amount FROM orders WHERE order_date >= '2023-01-01' -- 谓词下推到子查询内部 ) AS subquery; ``` --- ### **谓词下推与子查询的关系** 1. **子查询不是必需**:谓词下推的核心是让优化器自动将过滤条件下推到数据源附近,即使没有显式子查询,优化器也可能对 JOIN 或普通查询进行下推。 - 例如:在 `JOIN` 前先过滤单表数据。 2. **子查询可能帮助手动优化**: 如果优化器未能自动下推谓词(如复杂查询或某些数据库限制),**手动将过滤条件写入子查询**可以强制实现下推,例如: ```sql -- 复杂查询中手动下推谓词 SELECT a.* FROM big_table a JOIN ( SELECT id FROM small_table WHERE category = 'books' -- 手动下推到子查询 ) b ON a.id = b.id; ``` --- ### **注意事项** 1. **优化器的智能性**:现代数据库(如 PostgreSQL、Oracle)通常会自动进行谓词下推,无需手动干预。 2. **场景限制**:某些情况无法下推,例如: - 过滤条件依赖外层查询的结果(如关联子查询)。 - 聚合函数后的过滤(需用 `HAVING` 而不是 `WHERE`)。 3. **并非所有子查询都高效**:滥用子查询可能导致临时表创建或重复计算,需结合执行计划分析。 --- ### **总结** - **谓词下推的核心**:尽早过滤数据,减少计算和 I/O 开销。 - **子查询的作用**:在某些场景中可辅助手动优化,但并非必须多用子查询。 - **优化建议**:依赖数据库执行计划(如 `EXPLAIN`),观察谓词是否被正确下推,必要时调整查询结构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值