本文关键字:SQL Server全文索引、CONTAINS、FREETEXT、CONTAINSTABLE、FREETEXTTABLE等谓词。
想象这样一个场景:在DataBase_name.dbo.Table_name中有一个名为Title(标题)和Contents(内容)的字段,现在需要查询在Title或者Contents中包括“qq”字符的所有记录。
面对这样的一个场景,我们通常都会写这样一个脚本:SELECT * FROM DataBase_name.dbo.Table_name WHERE Title LIKE '%qq%' OR Contents LIKE '%qq%'; 没错,这也是我第一个想到的方法。
但是我们需要思考的是:随着时间的推移,数据会越来越大,那个时候我们该如何提高我们的性能?客户随时都有可能要求加入对Remark(备注)字段的查询,难道我们就应该不厌其烦地修改程序代码?
面对上面的质问,我们需要提醒你的是:①对于这样的查询条件,即使Title和Contents上都有索引,我们也无法使用到索引,因为在 '%qq%'的“qq”前面使用了通配符,所以无法使用到索引;如果查询的条件是'qq%',那倒是可以利用上索引。②在许多数据库性能调优的文章上都说OR这个谓词可以使用SELECT UNION ALL SELECT这样的方式来提高性能,但是需要提醒大家的是:如果在一条记录中字段Title和Contents都同时存在“中国”字符的话,那么返回的结果就会出现两条相同的记录,如果你希望是唯一的记录,那么这个时候你就要注意了。
现在回到我们上面提出的疑问上,大概这个时候大家都应该想到了数据库的全文索引了。全文索引是一种特殊类型的基于标记的功能性索引,由 Microsoft SQL Server 全文引擎 (MSFTESQL) 服务创建和维护。创建全文索引的过程与创建其他类型的索引的过程差别很大。MSFTESQL 不是基于某一特定行中存储的值来构造 B 树结构,而是基于要索引的文本中的各个标记来创建倒排、堆积且压缩的索引结构。
讲了那么久,硬伤在哪里呢?可能大家都怀疑我是不是标题党了,呵呵,马上就讲到,那就是这个全文索引能解决我们一开始提到的场景吗?回答是否定。为什么呢?因为SQL Server对字符串“tqq.tencent.com”进行分词和倒排索引后,我们是无法通过查询条件‘“*qq*”’来返回上面那条字符串的记录的,这样的查询条件只能查询到类似“qqt.tencent.com”、“www.qq.com”这样的字符串。SQL Server的分词应该是正向最大值的分词方法,它没有把字符串进行反方向再进行一次分词和索引,所以只能查询到词或短语的前缀符合的记录。这一点有可能会被大家所忽略掉。
就针对上面的说法,我们来进行测试一下:
--已经对表Test_FullText_Index的uri,uri_path建立了全文索引.
--下面的查询是为了说明CONTAINS与LIKE的区别.
SELECT ID,uri,uri_path
FROM Test_FullText_Index
where uri LIKE '%qq%'
AND ID NOT IN(SELECT ID FROM Test_FullText_Index WHERE CONTAINS(uri,'"qq*"')) --下图为执行结果
如何大家有什么好的解决方案可以解决这样的Like查询的话,可以拿出来大家探讨一下。
主题的内容讲完了,下面附带讲一些创建全文索引的步骤和注意事项,懂的童鞋(同学)可以跳过。
- 表中必须有一个唯一性索引,当并不需要是主键。
- 一个表中只能有一个全文索引。
- 你需要告诉你的脚本你想使用全文索引,如何告诉呢?那就是使用关键字:CONTAINS、FULLTEXT、CONTAINSTABLE、FREETEXTTABLE。例如:SELECT * FROM table_name WHERE CONTAINS(fullText_column,'"search contents*"');需要记住CONTAINS等在不同场景、需求下的用法。
- 如果定义了变量作为传入值,那么就要注意是否需要在set字符的时候的前面加入N标识。
- 要对表设置全文索引,那就得先对数据库设置了全文索引,这样点击表右键的时候,“全文索引”选项才能用。
- 脚本在查找的时候是不区分大小写的。解决办法:SELECT * FROM Table_name WHERE Column_name='A' COLLATE Chinese_PRC_CS_AI;或者SELECT * FROM Table_name WHERE ASCII(Column_name) = ASCII('A');
- Microsoft SQL Server 全文引擎 (MSFTESQL) 不是基于某一特定行中存储的值来构造 B 树结构,而是基于要索引的文本中的各个标记来创建倒排、堆积且压缩的索引结构。
- 全文索引并不一定能达到like这个谓词的效果,如LIKE '%qq%'。这正是本篇文章想要说明的。
- 如果数据库是在移动盘符上,好像就无法设置:数据库-属性-文件-“使用全文索引”了,这个时候chckbox是不可用的。(这个大家可以求证一下)
- 关于搜索结果的排序问题,全文索引并没有这个功能,也就是匹配度排序或者说是相似度排序。
- Lucene中有一个Similarity类,Lucene Practical Scoring Function就包含了得分的计算公式,tf、idf。
CONTAINS 谓词可以搜索:
- 词或短语。
- 词或短语的前缀。
- 与另一个词相邻的词。
- 由另一个词的词形变化而生成的词(例如,drive 一词是 drives、drove、driving 和 driven 词形变化的词干)。
- 使用同义词库确定的另一个词的同义词(例如,metal 一词可能有 aluminum 和 steel 等同义词)。
SQL Server 全文索引的硬伤(转载)的更多相关文章
-
SQL Server 全文索引的硬伤
本文关键字:SQL Server全文索引.CONTAINS.FREETEXT.CONTAINSTABLE.FREETEXTTABLE等谓词. 想象这样一个场景:在DataBase_name.dbo.T ...
-
SQL Server 全文索引介绍(转载)
概述 全文引擎使用全文索引中的信息来编译可快速搜索表中的特定词或词组的全文查询.全文索引将有关重要的词及其位置的信息存储在数据库表的一列或多列中.全文索引是一种特殊类型的基于标记的功能性索引,它是由 ...
-
SQL Server 全文索引创建
在安装数据库管理系统SQL Server 后,默认情况下全文索引的服务是没有开启的 ,所以首先需要先开启服务,在sql server配置管理器中 (sql server configuration M ...
-
SQL Server 全文索引的管理
全文索引不同于常见的聚集索引或非聚集索引,这些索引的内部实现是平衡树(B-Tree)结构,而全文索引在物理上是由一系列的内部表(Internal tables)构成的,这些内部表称作全文索引片段(Fr ...
-
SQL查询优化:详解SQL Server非聚集索引(转载)
本文是转载,原文地址 http://tech.it168.com/a2011/1228/1295/000001295176.shtml 在SQL SERVER中,非聚集索引其实可以看作是一个含有聚集索 ...
-
sql server 行转列(转载)
SQL Server中行列转换 Pivot UnPivot PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PI ...
-
SQL SERVER CURSOR游标的使用(转载)
一:认识游标 游标(Cursor)它使用户可逐行访问由SQL Server返回的结果集. 使用游标(cursor)的一个主要的原因就是把集合操作转换成单个记录处理方式. 用SQL语言从数据库中检索数据 ...
-
SQL Server 2005 数据库复制(转载)
对于一个地域分散的大型企业组织来说,构建具有典型的分布式计算机特征的大型企业管理信息系统时,总要解决一个很重要的问题:如何在多个不同数 据库服务器之间保证共享数据的一致性.之所以有这个重要的问题在于企 ...
-
SQL Server 的远程连接(转载)
SQL Server默认是不允许远程连接的,如果想要在本地用SSMS连接远程服务器上的SQLServer2012数据库,需要确认以下环节: 1)如果是工作组环境,则需要使用SQL Server身份验证 ...
随机推荐
-
ASP.Net系列教程
Getting Started with ASP.NET MVC This is a beginner tutorial that introduces the basics of ASP.NET M ...
-
tyvj1012 P1012 - 火柴棒等式 ——暴力枚举
题目链接:https://www.tyvj.cn/Problem_Show.aspx?id=1012 可以发现:最大的数字绝对不超过999,只要枚举出0-999所有数字需要的火柴数,然后再枚举C和A, ...
-
HW2.17
import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner i ...
-
201521123112《Java程序设计》第4周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点 1.2 使用常规方法总结其他上课内容 关于多态,多态性就是相同的形态,不同的定义.在简单点说的话就是不同类的对象对同一个消息作出的相应 ...
-
ECMA Script 6_数组的扩展_扩展运算符
1. 扩展运算符 内部调用的是数据结构的 Iterator 接口, 因此只要具有 Iterator 接口的对象,都可以使用扩展运算符 ... 如 map,,,, [...arr] 扩展运算符(spre ...
-
Educational Codeforces Round 43 (Rated for Div. 2)
Educational Codeforces Round 43 (Rated for Div. 2) https://codeforces.com/contest/976 A #include< ...
-
关于TypeError: strptime() argument 1 must be str, not bytes解析
关于TypeError: strptime() argument 1 must be str, not bytes解析 在使用datetime.strptime(s,fmt)来输出结果日期结果时, ...
-
ORB feature(O for orientation)
参考链接:http://blog.csdn.net/yang843061497/article/details/38553765 绪论 假如我有2张美女图片,我想确认这2张图片中美女是否是同一个人.这 ...
-
双向重定向tee命令详解
vim一般在训练网络的时候需要保存log文件,同时需要在屏幕上网络的输出信息,在shell文件中常常会看到如下代码 执行的命令 2>&1 | tee log.txt tee是linux中 ...
-
nodejs基础 -- 全局对象
全局对象:javascript中的一个特殊对象 全局变量:该特殊对象及其所有属性 该对象为:在浏览器javascript中,为window:在nodejs中,为global(所有全局变量都是globa ...