现有的数据库系统,绝大多数是以结构化数据检索的主要目标,因此实现相对简单。比如数值检索,可以建立一张排序好的索引表,这样速度可以得到提高。但对于非结构化数据,即全文数据,要想实现检索,一般都是采用模糊查询的方式实现的,这种方式不仅速度慢,而且容易将汉字错误切分,于是产生了全文检索技术。
全文检索技术是智能信息管理的关键技术之一,其主要目的就是实现对大容量的非结构化数据的快速查找。
全文检索的中文分词依赖系统词库,该词库是只读的,不允许修改。学过solr的都知道分词器(可以将一段内容分成多个短语)。
一般情况下,在插入或装载了数据后,为表创建索引会更加有效率,如果装载数据之前创建一个或多个索引,在插入每行时都必须更改和维护每个索引,会使得插入效率降低。
使用下面的准则决定何时创建索引:
1. 如果需要经常地检索大表中的少量的行,就为查询键创建索引
2. 为了改善多个表的链接性能,可以为连接列创建索引
3. 主键和唯一键自动有索引,外键很多情况也会自动创建索引
4. 小表不需要索引
选取索引列时考虑几点:
1.列中的值相对比较唯一;
2. 取值范围大,适合建立索引
3. CLOB和TEXT只能建立全文索引,BLOB不能建立任何索引(适用于ORACLE和国产的达梦数据库)
在create index 语句中列的排序会影响查询的性能。通常将最常用的列放在最前面。
如果多个字段组合定位,不要为每个字段都建立索引,考虑组合索引。当两个或多个字段都是等值查询时,组合索引中各个列的前后关系是无关紧要的;但如果是非等值查询,要想有效利用组合索引,则应该按照等值字段在前、非等值字段在后的原则创建组合索引。
一个表可以有任意数量的所有。但是索引越多修改数据的开销就越大。当一个表主要用于读时,索引多就有好处。
全文索引以词为基础的,MySQL默认的分词是所有非字母和数字的特殊符号都是分词符,与索引有关的几个变量如下:
mysql> SHOW VARIABLES LIKE ‘ft%‘; +--------------------------+----------------+ | Variable_name | Value | +--------------------------+----------------+ | ft_boolean_syntax | + -><()~*:""&| | | ft_max_word_len | 84 | | ft_min_word_len | 4 | | ft_query_expansion_limit | 20 | | ft_stopword_file | (built-in) | +--------------------------+----------------+ 5 rows in set, 1 warning (0.08 sec)
ft_boolean_syntax:改变IN BOOLEAN MODE的查询字符,不用重新启动MySQL也不用重建索引
ft_max_word_len : #最长的索引字符串,默认值为84,修改后必须重建索引文件
ft_min_word_len : #最短的索引字符串,默认值为4,(通常改为1)修改后必须重建索引文件
ft_query_expansion_limit: #查询括展时取最相关的几个值用作二次查询
ft_stopword_file (built-in):#全文索引的过滤词文件
1.建表的时候创建全文索引
CREATE TABLE article ( id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, title VARCHAR(200), body TEXT, FULLTEXT(title, body) );
mysql> show create table article\G *************************** 1. row *************************** Table: article Create Table: CREATE TABLE `article` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(200) DEFAULT NULL, `body` text, PRIMARY KEY (`id`), FULLTEXT KEY `title` (`title`,`body`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec)
2. 查看索引
SHOW INDEX FROM article;
3. 删除索引
DROP INDEX title ON article;
4. 修改表结构创建索引
ALTER TABLE `article` ADD FULLTEXT title_f (title,body);
或者
ALTER TABLE `article` ADD FULLTEXT INDEX title_f (title,body);
5. 直接创建索引 (重要)
CREATE FULLTEXT INDEX title_f ON article (title, body)
补充:上面建的是联合索引,下面创建单列索引
CREATE FULLTEXT INDEX body_f ON article ( body)
6. 使用索引(如果对没有全文索引的列进行match会报错)
使用全文索引的格式: MATCH (columnName) AGAINST (‘string‘)
例如:
查询包含精忠报国的数据:
SELECT * FROM article WHERE MATCH(body ) AGAINST(‘精忠报国‘);
7. 全文本布尔操作符
布尔操作符 | 说明 |
+ | 包含,词必须存在 |
- | 排除,词必须不出现 |
> | 包含,而且增加等级值 |
< | 包含,且减少等级值 |
() | 把词组成子表达式(允许这些子表达式作为一个组被包含、排除、排列等) |
~ | 取消一个词的牌谑值 |
* | 词尾的通配符。这个只能放在词后面 |
"" | 定义一个短语(与单个词的列表不一样,它匹配整个短语以便包含或排除这个短语) |
例如:
+:查询必须包含精忠报国的:
SELECT * FROM article WHERE MATCH(body ) AGAINST(‘+精忠报国‘ IN BOOLEAN MODE );
-:必须不包含精忠报国的:
SELECT * FROM article WHERE MATCH(body ) AGAINST(‘-精忠报国‘ IN BOOLEAN MODE );
空格:查询包含史无前例或者大义灭亲的
SELECT * FROM article WHERE MATCH(body ) AGAINST(‘史无前例 大义灭亲‘ IN BOOLEAN MODE );
>:查询包含精忠报国的,如果包含大义灭亲的往前排
SELECT * FROM article WHERE MATCH(body ) AGAINST(‘精忠报国 >大义灭亲‘ IN BOOLEAN MODE );
<:查询包含精忠报国的,如果包含大义灭亲的往后排
SELECT * FROM article WHERE MATCH(body ) AGAINST(‘精忠报国 <大义灭亲‘ IN BOOLEAN MODE );
*:查询以大义灭亲结尾的
SELECT * FROM article WHERE MATCH(body ) AGAINST(‘+精忠报国*‘ IN BOOLEAN MODE );
主要介绍三种自然语言的分析器:
basic_lexer(默认的分析器):主要针对英语。有较高的处理效率,因为它只认空格和标点,所以对于汉语没有空格的情况不会分词
chinese_vgram_lexer: 专用汉语分析器,支持所有汉字字符集,因为采用了分词的方法,可以查到所有的分词,效率差
chinese_lexer: 新汉语分析器,只支持utf8, 支持识别大部分的分词,但是会过滤掉很多无法识别的分词,因为这个原因也导致效率很高,如果数据库是zhs16gbk字符集,则只能使用Chinese vgram lexer
注意:追求效率那么使用CHINESE_LEXER,如果追求准确度那么使用CHINESE_VGRAM_LEXER(推荐使用chinese_vgram_lexer)
BEGIN ctx_ddl.create_preference (‘my_lexer‘, ‘chinese_vgram_lexer‘); END;
BEGIN ctx_ddl.drop_preference (‘my_lexer‘); end;
CREATE INDEX prop_2_f ON 合同2(档案属性) indextype is ctxsys.context parameters(‘lexer my_lexer‘);
包含:
select id from 合同2 where contains(档案属性, ‘测试档案属性‘) > 0
不包含:
select id from 合同2 where not contains(档案属性, ‘测试档案属性‘) > 0
drop index prop_2_f
begin ctx_ddl.optimize_index(‘prop_2_f‘,‘full‘); END;
原文:https://www.cnblogs.com/qlqwjy/p/11328895.html