【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数据库的角度,有什么方法呢?

我觉得通过使用全文检索,能少做不少的无用功。下面是例子。

一、首先是普通的方法:


  1. set statistics io on
  2. set statistics time on
  3. create database wc
  4. go
  5. use wc
  6. go
  7. create table tbl_word
  8. (
  9. i int not null primary key identity(1,1),
  10. v nvarchar(max) --存储大量文字
  11. )
  12. go
  13. --delete from tbl_word
  14. insert into tbl_word
  15. values(‘我的一个兴趣是看电影。‘),
  16. (‘我的一个爱好是看电影和电视剧‘)
  17. insert into tbl_word
  18. values(replicate(‘我的一个爱好是看电影和电视剧‘,1000) + ‘兴趣‘ +
  19. replicate(‘我的爱好是看电视剧和film和动漫‘,1500))
  20. go 1000
  21. insert into tbl_word
  22. values(‘我的一个兴趣是看电影。‘),
  23. (‘我的一个爱好是看电影和电视剧‘)
  24. go 100
  25. insert into tbl_word
  26. values(replicate(‘我的一个爱好是看电影和电视剧‘,1000) + ‘haha‘ +
  27. replicate(‘我的爱好是看电视剧和film和动漫‘,1500))
  28. go
  29. /*
  30. SQL Server 分析和编译时间:
  31. CPU 时间 = 0 毫秒,占用时间 = 3 毫秒。
  32. (1 行受影响)
  33. 表 ‘tbl_word‘。扫描计数 1,逻辑读取 1509 次,物理读取 0 次,预读 0 次,lob 逻辑读取 5 次,lob 物理读取 0 次,lob 预读 0 次。
  34. SQL Server 执行时间:
  35. CPU 时间 = 484 毫秒,占用时间 = 490 毫秒。
  36. */
  37. select *
  38. from tbl_word
  39. where v like ‘%haha%‘

二、全文检索的方法:


  1. create fulltext catalog cat_production_document
  2. go
  3. --从系统干扰词表,来创建自定义的干扰词表,因为系统干扰词表是无法修改的
  4. CREATE FULLTEXT STOPLIST WCX
  5. from system stoplist;
  6. go
  7. create fulltext index on dbo.tbl_word --在这个表上建全文索引
  8. (
  9. v
  10. )
  11. key index PK__tbl_word__3BD019960BC6C43E --键索引,一般是表的主键,这里需要修改为具体的名称
  12. on cat_production_document --全文目录
  13. with (CHANGE_TRACKING AUTO, --全文索引会随着表数据的修改而自动更新
  14. StopList=wcx); --是用自定义的干扰字表
  15. go
  16. ALTER FULLTEXT INDEX ON dbo.tbl_word
  17. enable
  18. go
  19. set statistics io on
  20. set statistics time on
  21. --查询基于变形的,字面的,同义的匹配方式搜索全文列
  22. --会返回要搜索文本中包含的单词以及单词的同义词,变形词(复数)的记录
  23. /*
  24. SQL Server 分析和编译时间:
  25. CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
  26. SQL Server 执行时间:
  27. CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
  28. SQL Server 分析和编译时间:
  29. CPU 时间 = 0 毫秒,占用时间 = 5 毫秒。
  30. (1 行受影响)
  31. 表 ‘tbl_word‘。扫描计数 0,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 3 次,lob 物理读取 0 次,lob 预读 0 次。
  32. (1 行受影响)
  33. SQL Server 执行时间:
  34. CPU 时间 = 0 毫秒,占用时间 = 10 毫秒。
  35. SQL Server 分析和编译时间:
  36. CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
  37. SQL Server 执行时间:
  38. CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
  39. */
  40. SELECT *
  41. from dbo.tbl_word
  42. WHERE FREETEXT (v, --带全文索引的列名
  43. ‘haha‘); --要搜索的文本

从上面的2段代码在执行时所消耗的时间,就可以清楚的看出2种方法的效率差异,全文索引的效率提高了50倍左右。

其实采用合适的技术(比如,这里的全文检索技术,就很适合模糊查询),就能提高不少性能。

3、全文检索的问题

有时候,我们发现有些词是找不到的,这个主要是因为干扰词的影响,比如我们查询"是",那么就没有记录返回。

通过dm_fts_parser,我们可以知道sql server 的全文服务,是如何来断词分词的。


  1. --1. 但是如果我们查询"是",会发现没有返回记录
  2. SELECT *
  3. from dbo.tbl_word
  4. WHERE FREETEXT (v, --带全文索引的列名
  5. ‘是‘); --要搜索的文本
  6. --2.查询地区标识
  7. select name,
  8. alias,
  9. lcid --地区标识符
  10. from sys.syslanguages
  11. where name = ‘简体中文‘
  12. /*
  13. name alias lcid
  14. 简体中文 Simplified Chinese 2052
  15. */
  16. --3.干扰词列表id
  17. select *
  18. from sys.fulltext_stoplists
  19. /*
  20. stoplist_id name
  21. 5 WCX
  22. */
  23. --4.是否可以被全文引擎识别,也就是对内容,断词后的结果
  24. --"是"是一个Noise Word ,也就是干扰词
  25. select special_term,
  26. display_term,
  27. source_term
  28. from sys.dm_fts_parser
  29. (‘我的一个兴趣是看电影。‘, --要搜索的字符串
  30. 2052, --地区标识符
  31. 5, --干扰词列表id
  32. 0) --是否区分重音
  33. /*
  34. special_term display_term source_term
  35. Noise Word 我 我的一个兴趣是看电影。
  36. Noise Word 的 我的一个兴趣是看电影。
  37. Noise Word 一 我的一个兴趣是看电影。
  38. Noise Word 个 我的一个兴趣是看电影。
  39. Exact Match 兴趣 我的一个兴趣是看电影。
  40. Noise Word 是 我的一个兴趣是看电影。
  41. Exact Match 看 我的一个兴趣是看电影。
  42. Exact Match 电影 我的一个兴趣是看电影。
  43. */
  44. --5.1 我们可以查询一下干扰词列表,发现 "是" 是一个干扰词
  45. SELECT stopword
  46. FROM sys.fulltext_stopwords
  47. WHERE language_id = 2052 and stopword = ‘是‘
  48. /*
  49. stopword
  50. */
  51. --5.2把干扰词"是"去掉
  52. ALTER FULLTEXT STOPLIST wcx
  53. DROP ‘是‘ language ‘Simplified Chinese‘;
  54. --5.3再次查询,没有结果返回,发现已去掉这个干扰词
  55. SELECT stopword
  56. FROM sys.fulltext_stopwords
  57. WHERE language_id = 2052 and stopword = ‘是‘
  58. --5.4 会返回3000多条记录
  59. SELECT *
  60. from dbo.tbl_word
  61. WHERE FREETEXT (v, --带全文索引的列名
  62. ‘是‘); --要搜索的文本
  63. --5.5 但考虑到这个"是"没什么意义,所以还是需要加到干扰词列表中
  64. ALTER FULLTEXT STOPLIST wcx
  65. add ‘是‘ language ‘Simplified Chinese‘;
  66. --5.6 再次查询,没有返回任何记录,说明干扰词起作用了
  67. SELECT *
  68. from dbo.tbl_word
  69. WHERE FREETEXT (v, --带全文索引的列名
  70. ‘是‘); --要搜索的文本
  71. --6.1 改成使用系统干扰词列表
  72. ALTER FULLTEXT INDEX on tbl_word --表名
  73. SET STOPLIST=system ;--指定使用的全文非索引字表为系统干扰词列表
  74. --6.2 启动填充,如果CHANGE_TRACKING != AUTO,则需要启动一次填充才使新设定的全文非索引字表生效;
  75. ALTER FULLTEXT INDEX on tbl_word --表名
  76. START FULL POPULATION

有的时候,我们要查询的单词,虽然不是Noise Word,但还是会查询不到,这个就是全文检索的分词的问题了

对于每种断字符语言,断词结果是无法改变的。如果实在想要改变,只能通过微软公布的接口,自行编程修改相应的组件。

不过我们可以通过修改 分词所使用的语言来尝试一下,比如一般是用2052,也就是简体中文,如果用1028,也就是繁体中文,那么就有可能达到合理分词的目的。


不想长大啊

发布了416 篇原创文章 · 获赞 135 · 访问量 94万+

他的留言板
关注

原文地址:https://www.cnblogs.com/lonelyxmas/p/12019948.html

时间: 2024-08-25 13:44:03

【SQL Server性能优化】运用SQL Server的全文检索来提高模糊匹配的效率的相关文章

SQL语句性能优化--LECCO SQL Expert

SQL语句的优化是将性能低下的SQL语句转换成目的相同的性能优异的SQL语句. 人工智能自动SQL优化就是使用人工智能技术,自动对SQL语句进行重写,从而找到性能最好的等效SQL语句. 数据库性能的优化   一个数据库系统的生命周期可以分成:设计.开发和成品三个阶段.在设计阶段进行数据库性能优化的成本最低,收益最大.在成品阶段进行数据库性能优化的成本最高,收益最小. 数据库的优化通常可以通过对网络.硬件.操作系统.数据库参数和应用程序的优化来进行.最常见的优化手段就是对硬件的升级.根据统计,对网

【SQL Server性能优化】SQL Server 2008该表压缩

当数据库是比较大的,而当你想备份,我们可以启动数据库备份压缩.这项由于备份文件比较小的压缩,所以整个备份的更快的速度,同时还低了磁盘空间的消耗. 当然还有一方面.肯定会添加cpu的消耗.只是一般的server都是多核.所以实际上对系统不会有大的影响. 事实上.不仅能够在备份的时候压缩,在SQL Server 2008中.我们还能够对表和索引进行压缩,以下通过压缩前.压缩后的比較.来展示SQL Server 2008强大的表及索引的压缩功能. 这里在公司測试数据库找了一个中型的表,共同拥有943万

【SQL Server性能优化】SQL Server 2008之表压缩

当数据库比较大,而要进行备份时,我们可以启动数据库备份的压缩,这样减少对于磁盘空间的消耗. 其实,不仅可以在备份的时候压缩,在SQL Server 2008中,我们还可以对表进行压缩,下面通过压缩前.压缩后的比较,来展示SQL Server 2008强大的表压缩功能. 这里在测试数据库找了一个较大的表,共有9439661 条记录, 1.压缩前表的大小 SP_SPACEUSED 'TB_WCB' /* name rows reserved data index_size unused TB_WCB

VMWare ESX Server性能优化

VMWare ESX Server性能优化 vmware ESX server 是当前服务器市场上基于intel平台的最流行的虚拟软件产品.对比其他虚拟软件产品,如 GSX server 和ms virtual server,ESX的最大优点就是可以大大减少host系统所占用资源的.ESX server内核直接运行在硬件之上,而且系统稳定性和性能都有很大的提高. ESX server也很适合企业级应用,因为它支持重要的冗余功能,比如多路经,以及链路绑定.由于有诸如p2v vmotion 和vir

SQL Server数据库性能优化之SQL语句篇(转载)

SQL Server数据库性能优化之SQL语句篇 原文地址:http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 期项目需要,做了一段时间的SQL Server性能优化,遇到了一些问题,也积累了一些经验,现总结一下,与君共享.SQL Server性能优化涉及到许多方面,如良好的系统和数据库设计,优质的SQL编写,合适的数据表索引设计,甚至各种硬件因素:网络性能.服务器的性能.操作系统的性能,甚至网卡.交换机等.这篇文章主

Sql Server 性能优化之包含列

Sql Server 性能优化之包含列 导读:数据数优化查询一直是个比较热门的话题,小生在这方面也只能算是个入门生.今 天我们就讲下数据库包含列这个一项的作用及带来的优化效果 引用下MSDN里面的一段解释: 当查询中的所有列都作为键列或非键列包含在索引中时,带有包含性非键列的索引可以显 著提高查询性能. 这样可以实现性能提升,因为查询优化器可以在索引中找到所有列值:不 访问表或聚集索引数据,从而减少磁盘 I/O 操作 上面这一段什么意思呢? 意思就是说设置好包含列,能提高查询性能,减少IO输出.

SQL Server 性能优化(一)——简介

原文:SQL Server 性能优化(一)--简介 一.性能优化的理由: 听起来有点多余,但是还是详细说一下: 1.节省成本:这里的成本不一定是钱,但是基本上可以变相认为是节省钱.性能上去了,本来要投入的硬件就可以减缓投入,从另外一个角度看来它就是节省了钱. 2.增加效率:对于客户来说,性能上去了,他们的工作效率也高了. 3.降低挫折感:性能底下,客户抱怨,无疑是对自己心灵上的打击. 二.性能误区: 性能误区 误区 现实 如果处理器使用率很高,那么需要添加更快的处理器 某一部分导致了性能问题 8

SQL Server数据库性能优化之SQL语句篇

SQL Server数据库性能优化之SQL语句篇 近期项目需要,做了一段时间的SQL Server性能优化,遇到了一些问题,也积累了一些经验,现总结一下,与君共享.SQL Server性能优化涉及到许多方面,如良好的系统和数据库设计,优质的SQL编写,合适的数据表索引设计,甚至各种硬件因素:网络性能.服务器的性能.操作系统的性能,甚至网卡.交换机等.这篇文章主要讲到如何改善SQL语句,还将有另一篇讨论如何改善索引.如何改善SQL语句的一些原则: 1. 按需索取字段,跟“SELECT *”说拜拜

SQL Server数据库性能优化之SQL语句篇【转】

SQL Server数据库性能优化之SQL语句篇http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 近期项目需要, 做了一段时间的SQL Server性能优化,遇到了一些问题,也积累了一些经验,现总结一下,与君共享.SQL Server性能优化涉及到许多方面,如良好的系统和数据库设计,优质的SQL编写,合适的数据表索引设计,甚至各种硬件因素:网络性能.服务器的性能. 操作系统的性能,甚至网卡.交换机等.这篇文章主要讲到