【SQL Server性能优化】运用SQL Server的全文检索来提高模糊匹配的效率
原文:【SQL Server性能优化】运用SQL Server的全文检索来提高模糊匹配的效率
今天去面试,这个公司的业务需要模糊查询数据,之前他们通过mongodb来存储数据,但他们说会有丢数据的问题,我从业务上了解到,显然对他们公司而言,丢数是绝对不能允许的。
另外,他们说之前也用过SQL Server的全文检索,但速度不够快,不如用mongodb快,当然我不太清楚他们所谓快的具体定义,比如查询只需要1秒,还是1分钟。他们的系统现在采用的是SQL Server,通过复制来实现高可用性,因为他们说备份数据库需要很长时间。我在想,这确实解决了可用性问题,但没解决性能问题,可以考虑分表,把大的表拆分到多个数据库,每个数据库可以通过复制来实现可用性。
我觉得他们可能更需要一个架构师,来决定采用何种技术解决他们现在的技术问题,因为这种技术问题,显然不是靠DBA的优化就能解决的;其次才是需要DBA,让DBA来管理、维护、优化系统。
当时在面试的时候,我表示虽然在博客里也写了一篇关于SQL Server全文索引的文章,但在实际工作中确实也没有用到。回去以后,我想了想,觉得这个问题还是可以通过SQL Server的全文索引来尝试一下。
引用自己之前写的一篇全文检索的文章: http://blog.csdn.net/yupeigu/article/details/7792955
上面的文章是去年写的,当时在看《SQL Server 2008 实战》这本书,看完后,觉得不能只是看书,不然很快就会忘记,于是在空闲的时候,把书上的东西实践了一下,算是装模做样的把书上的代码抄写了一遍,就算是实践过了,放心了。但其实很快就忘记了,就算抄写10遍,也会忘记,学了不用等于不学。不过这也没办法,因为学了这个全文检索,公司里也用不到。
现在回想一下,这种实践有点像以前小学和初中时抄写错别字一下,字写错了,老师会说:“你把这个句子抄写100遍”,一开始抄写的时候,还挺认真的,但写了一会,手就开始酸了。
于是手上握着5支笔,开始抄写,这样就能一次抄写5遍,效率提高了好多倍,现在想想这个是偷工减料,但也包含了优化的思想,那就是同时用更多的资源(这里是5支笔)来做事。
但再想想,其实这种学习效率其实是很差的,本质上就是做了不少的无用功,没必要抄写那么多遍,所以就有另一种优化,那就是少做无用之事,少做无用功。
言归正传,现在有这样一个问题,有个字段,文本型的,可能会有上万个文字,现在要从表中,通过这个字段的文本,找到复合要求的记录,那么从SQL Server数据库的角度,有什么方法呢?
我觉得通过使用全文检索,能少做不少的无用功。下面是例子。
一、首先是普通的方法:
-
set statistics io on
-
set statistics time on
-
-
create database wc
-
go
-
-
use wc
-
go
-
-
-
create table tbl_word
-
(
-
i int not null primary key identity(1,1),
-
v nvarchar(max) --存储大量文字
-
)
-
go
-
--delete from tbl_word
-
-
insert into tbl_word
-
values('我的一个兴趣是看电影。'),
-
('我的一个爱好是看电影和电视剧')
-
-
insert into tbl_word
-
values(replicate('我的一个爱好是看电影和电视剧',1000) + '兴趣' +
-
replicate('我的爱好是看电视剧和film和动漫',1500))
-
-
go 1000
-
-
insert into tbl_word
-
values('我的一个兴趣是看电影。'),
-
('我的一个爱好是看电影和电视剧')
-
-
go 100
-
-
insert into tbl_word
-
values(replicate('我的一个爱好是看电影和电视剧',1000) + 'haha' +
-
replicate('我的爱好是看电视剧和film和动漫',1500))
-
-
go
-
-
-
/*
-
SQL Server 分析和编译时间:
-
CPU 时间 = 0 毫秒,占用时间 = 3 毫秒。
-
-
(1 行受影响)
-
表 'tbl_word'。扫描计数 1,逻辑读取 1509 次,物理读取 0 次,预读 0 次,lob 逻辑读取 5 次,lob 物理读取 0 次,lob 预读 0 次。
-
-
SQL Server 执行时间:
-
CPU 时间 = 484 毫秒,占用时间 = 490 毫秒。
-
*/
-
select *
-
from tbl_word
-
where v like '%haha%'
二、全文检索的方法:
-
create fulltext catalog cat_production_document
-
go
-
-
-
--从系统干扰词表,来创建自定义的干扰词表,因为系统干扰词表是无法修改的
-
CREATE FULLTEXT STOPLIST WCX
-
from system stoplist;
-
go
-
-
-
create fulltext index on dbo.tbl_word --在这个表上建全文索引
-
(
-
v
-
)
-
key index PK__tbl_word__3BD019960BC6C43E --键索引,一般是表的主键,这里需要修改为具体的名称
-
on cat_production_document --全文目录
-
with (CHANGE_TRACKING AUTO, --全文索引会随着表数据的修改而自动更新
-
StopList=wcx); --是用自定义的干扰字表
-
go
-
-
-
ALTER FULLTEXT INDEX ON dbo.tbl_word
-
enable
-
go
-
-
set statistics io on
-
set statistics time on
-
-
--查询基于变形的,字面的,同义的匹配方式搜索全文列
-
--会返回要搜索文本中包含的单词以及单词的同义词,变形词(复数)的记录
-
/*
-
SQL Server 分析和编译时间:
-
CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
-
-
SQL Server 执行时间:
-
CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
-
SQL Server 分析和编译时间:
-
CPU 时间 = 0 毫秒,占用时间 = 5 毫秒。
-
-
(1 行受影响)
-
表 'tbl_word'。扫描计数 0,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 3 次,lob 物理读取 0 次,lob 预读 0 次。
-
-
(1 行受影响)
-
-
SQL Server 执行时间:
-
CPU 时间 = 0 毫秒,占用时间 = 10 毫秒。
-
SQL Server 分析和编译时间:
-
CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
-
-
SQL Server 执行时间:
-
CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
-
-
*/
-
SELECT *
-
from dbo.tbl_word
-
WHERE FREETEXT (v, --带全文索引的列名
-
'haha'); --要搜索的文本
从上面的2段代码在执行时所消耗的时间,就可以清楚的看出2种方法的效率差异,全文索引的效率提高了50倍左右。
其实采用合适的技术(比如,这里的全文检索技术,就很适合模糊查询),就能提高不少性能。
3、全文检索的问题
有时候,我们发现有些词是找不到的,这个主要是因为干扰词的影响,比如我们查询"是",那么就没有记录返回。
通过dm_fts_parser,我们可以知道sql server 的全文服务,是如何来断词分词的。
-
--1. 但是如果我们查询"是",会发现没有返回记录
-
SELECT *
-
from dbo.tbl_word
-
WHERE FREETEXT (v, --带全文索引的列名
-
'是'); --要搜索的文本
-
-
-
-
--2.查询地区标识
-
select name,
-
alias,
-
lcid --地区标识符
-
from sys.syslanguages
-
where name = '简体中文'
-
/*
-
name alias lcid
-
简体中文 Simplified Chinese 2052
-
*/
-
-
-
--3.干扰词列表id
-
select *
-
from sys.fulltext_stoplists
-
/*
-
stoplist_id name
-
5 WCX
-
*/
-
-
-
--4.是否可以被全文引擎识别,也就是对内容,断词后的结果
-
--"是"是一个Noise Word ,也就是干扰词
-
select special_term,
-
display_term,
-
source_term
-
from sys.dm_fts_parser
-
('我的一个兴趣是看电影。', --要搜索的字符串
-
2052, --地区标识符
-
5, --干扰词列表id
-
0) --是否区分重音
-
/*
-
special_term display_term source_term
-
Noise Word 我 我的一个兴趣是看电影。
-
Noise Word 的 我的一个兴趣是看电影。
-
Noise Word 一 我的一个兴趣是看电影。
-
Noise Word 个 我的一个兴趣是看电影。
-
Exact Match 兴趣 我的一个兴趣是看电影。
-
Noise Word 是 我的一个兴趣是看电影。
-
Exact Match 看 我的一个兴趣是看电影。
-
Exact Match 电影 我的一个兴趣是看电影。
-
*/
-
-
-
-
--5.1 我们可以查询一下干扰词列表,发现 "是" 是一个干扰词
-
SELECT stopword
-
FROM sys.fulltext_stopwords
-
WHERE language_id = 2052 and stopword = '是'
-
/*
-
stopword
-
是
-
*/
-
-
-
--5.2把干扰词"是"去掉
-
ALTER FULLTEXT STOPLIST wcx
-
DROP '是' language 'Simplified Chinese';
-
-
-
-
--5.3再次查询,没有结果返回,发现已去掉这个干扰词
-
SELECT stopword
-
FROM sys.fulltext_stopwords
-
WHERE language_id = 2052 and stopword = '是'
-
-
-
-
--5.4 会返回3000多条记录
-
SELECT *
-
from dbo.tbl_word
-
WHERE FREETEXT (v, --带全文索引的列名
-
'是'); --要搜索的文本
-
-
-
-
--5.5 但考虑到这个"是"没什么意义,所以还是需要加到干扰词列表中
-
ALTER FULLTEXT STOPLIST wcx
-
add '是' language 'Simplified Chinese';
-
-
-
-
--5.6 再次查询,没有返回任何记录,说明干扰词起作用了
-
SELECT *
-
from dbo.tbl_word
-
WHERE FREETEXT (v, --带全文索引的列名
-
'是'); --要搜索的文本
-
-
-
-
-
--6.1 改成使用系统干扰词列表
-
ALTER FULLTEXT INDEX on tbl_word --表名
-
SET STOPLIST=system ;--指定使用的全文非索引字表为系统干扰词列表
-
-
-
--6.2 启动填充,如果CHANGE_TRACKING != AUTO,则需要启动一次填充才使新设定的全文非索引字表生效;
-
ALTER FULLTEXT INDEX on tbl_word --表名
-
START FULL POPULATION
有的时候,我们要查询的单词,虽然不是Noise Word,但还是会查询不到,这个就是全文检索的分词的问题了
对于每种断字符语言,断词结果是无法改变的。如果实在想要改变,只能通过微软公布的接口,自行编程修改相应的组件。
不过我们可以通过修改 分词所使用的语言来尝试一下,比如一般是用2052,也就是简体中文,如果用1028,也就是繁体中文,那么就有可能达到合理分词的目的。
【SQL Server性能优化】运用SQL Server的全文检索来提高模糊匹配的效率的更多相关文章
- 神奇的 SQL 之性能优化 → 让 SQL 飞起来
开心一刻 一天,一个男人去未婚妻家玩,晚上临走时下起了大雨 未婚妻劝他留下来过夜,说完便去准备被褥,准备就绪后发现未婚夫不见了 过了好久,全身淋的像只落汤鸡的未婚夫回来了 未婚妻吃惊的问:" ...
- 【SQL Server性能优化】SQL Server 2008该表压缩
当数据库是比较大的,而当你想备份,我们可以启动数据库备份压缩.这项由于备份文件比较小的压缩,所以整个备份的更快的速度,同时还低了磁盘空间的消耗. 当然还有一方面.肯定会添加cpu的消耗.只是一般的se ...
- SQL Server数据库性能优化之SQL语句篇【转】
SQL Server数据库性能优化之SQL语句篇http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 近期项目需要, 做了一 ...
- SQL Server 性能优化(一)——简介
原文:SQL Server 性能优化(一)--简介 一.性能优化的理由: 听起来有点多余,但是还是详细说一下: 1.节省成本:这里的成本不一定是钱,但是基本上可以变相认为是节省钱.性能上去了,本来要投 ...
- SQL Server 性能优化之——系统化方法提高性能
SQL Server 性能优化之——系统化方法提高性能 阅读导航 1. 概述 2. 规范逻辑数据库设计 3. 使用高效索引设计 4. 使用高效的查询设计 5. 使用技术分析低性能 6. 总结 1. 概 ...
- SQL Server性能优化与管理的艺术 附件下载地址
首先感谢读者们对鄙人的支持,购买了<SQL Server性能优化与管理的艺术>,由于之前出版社的一些疏忽,附件没有上传成功,再次本人深表歉意. 请需要下载附件的读者从下面链接下载,谢谢: ...
- Dynamics AX 2012 性能优化之 SQL Server 复制
Dynamics AX 2012 性能优化之 SQL Server 复制 分析数据滞后 在博文 Dynamics AX 2012 在BI分析中建立数据仓库的必要性 里,Reinhard 阐述了在 AX ...
- SQL Server性能优化(6)查询语句建议
1. 如果对数据不是工业级的访问(允许脏读),在select里添加 with(nolock) ID FROM Measure_heat WITH (nolock) 2. 限制结果集的数据量,如使用TO ...
- SQL SERVER性能优化综述
SQL SERVER性能优化综述 一个系统的性能的提高,不单单是试运行或者维护阶段的性能调优的任务,也不单单是开发阶段的事情,而是在整个软件生命周期都需要注意,进行有效工作才能达到的.所以我希望按照软 ...
随机推荐
- SQL中如何使用方向键——lrwrap
Linux alias命令用于设置指令的别名. 用户可利用alias,自定指令的别名.若仅输入alias,则可列出目前所有的别名设置.alias的效力仅及于该次登入的操作.若要每次登入是即自动设好别名 ...
- Row_Number() and Rank() in SQL
1. 数据表实例数据 2. 使用Row_Number()方法给每一行数据添加一个唯一编号, 可以按照某一列进行排序. 3. 使用Partition by Column在一个Partition内进行编号 ...
- osg create shape
osg::ref_ptr<osg::Node> OSG_Qt_::createSimple() { osg::ref_ptr<osg::Geode> geode = new o ...
- python 中 staticmethod 和 classmethod有什么区别
面试中经常会问到staticmethod 和 classmethod有什么区别? 首先看下官方的解释: staticmethod: class staticmethod staticmethod(fu ...
- OpenStack Magnum项目简介
1 项目简介 Magnum是OpenStack中一个提供容器集群部署的服务. Magnum是一个Pass层的OpenStack项目. Magnum使用Heat部署一个包含Docker和Kubernet ...
- Hibernatne 缓存中二级缓存简单介绍
hibernate的session提供了一级缓存,每个session,对同一个id进行两次load,不会发送两条sql给数据库,但是session关闭的时候,一级缓存就失效了. 二级缓存是Sessio ...
- TEC-2机微程序设计
了解TEC-2机的结构和基本的指令知识很重要,不理解而只知一味地照抄是学不到知识的.建议先阅读课件,再结合例子进行理解.以下例子只供参考,有些地方可以合并,具体的操作仍需见仁见智.理解并学会使用微指令 ...
- 获取网卡名称及其IP地址的方法
代码 # -*- coding: utf-8 -*- import psutil #获取网卡名称和其ip地址,不包括回环 def get_netcard(): netcard_info = [] in ...
- 转:TSDF in Kinect fusion
KinectFusion中用到的TSDF Fusion 原po:https://blog.csdn.net/qq_31785865/article/details/78524429 最近在看关于稠密三 ...
- Time & Space Complexity
Quick Sort: Time complexity: best case O(n*lgn), worst case O(n^2) Space complexity: Best case O(lgn ...