zoukankan      html  css  js  c++  java
  • 全文索引

      现有的数据库系统,绝大多数是以结构化数据检索的主要目标,因此实现相对简单。比如数值检索,可以建立一张排序好的索引表,这样速度可以得到提高。但对于非结构化数据,即全文数据,要想实现检索,一般都是采用模糊查询的方式实现的,这种方式不仅速度慢,而且容易将汉字错误切分,于是产生了全文检索技术。

      全文检索技术是智能信息管理的关键技术之一,其主要目的就是实现对大容量的非结构化数据的快速查找。

      全文检索的中文分词依赖系统词库,该词库是只读的,不允许修改。学过solr的都知道分词器(可以将一段内容分成多个短语)。

      全文索引不能达到like的效果,因为会分词,所以连着的两个字不一定正好会分成一个词。

     1.  索引的准则

    1.在表中插入数据后创建索引

      一般情况下,在插入或装载了数据后,为表创建索引会更加有效率,如果装载数据之前创建一个或多个索引,在插入每行时都必须更改和维护每个索引,会使得插入效率降低。

    2.索引正确的表和列

      使用下面的准则决定何时创建索引:

    1.  如果需要经常地检索大表中的少量的行,就为查询键创建索引

    2. 为了改善多个表的链接性能,可以为连接列创建索引

    3. 主键和唯一键自动有索引,外键很多情况也会自动创建索引

    4. 小表不需要索引

      选取索引列时考虑几点:

    1.列中的值相对比较唯一;

    2. 取值范围大,适合建立索引

    3. CLOB和TEXT只能建立全文索引,BLOB不能建立任何索引(适用于ORACLE和国产的达梦数据库)

    3. 为性能而安排索引列

      在create index 语句中列的排序会影响查询的性能。通常将最常用的列放在最前面。

      如果多个字段组合定位,不要为每个字段都建立索引,考虑组合索引。当两个或多个字段都是等值查询时,组合索引中各个列的前后关系是无关紧要的;但如果是非等值查询,要想有效利用组合索引,则应该按照等值字段在前、非等值字段在后的原则创建组合索引。

    4.限制索引数量

      一个表可以有任意数量的所有。但是索引越多修改数据的开销就越大。当一个表主要用于读时,索引多就有好处。

    2.  mysql全文索引的用法

    0.  简介

      全文索引以词为基础的,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. mysql中全文索引

    1.建表的时候创建全文索引

     CREATE TABLE article ( 
                      id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, 
                      title VARCHAR(200), 
                      body TEXT, 
                     FULLTEXT(title, body) 
                  );
    mysql> show create table articleG
    *************************** 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 );

    3.  Oracle全文索引用法

     主要介绍三种自然语言的分析器:

    basic_lexer(默认的分析器):主要针对英语。有较高的处理效率,因为它只认空格和标点,所以对于汉语没有空格的情况不会分词

    chinese_vgram_lexer: 专用汉语分析器,支持所有汉字字符集,因为采用了分词的方法,可以查到所有的分词,效率差

    chinese_lexer: 新汉语分析器,只支持utf8, 支持识别大部分的分词,但是会过滤掉很多无法识别的分词,因为这个原因也导致效率很高,如果数据库是zhs16gbk字符集,则只能使用Chinese vgram lexer
    注意:追求效率那么使用CHINESE_LEXER,如果追求准确度那么使用CHINESE_VGRAM_LEXER(推荐使用chinese_vgram_lexer)

     1.  创建文本解析器

    BEGIN
      ctx_ddl.create_preference ('my_lexer', 'chinese_vgram_lexer');
    END;

    2.  删除文本解析器

    BEGIN
       ctx_ddl.drop_preference ('my_lexer');
       end;

    3.   创建全文索引

    CREATE INDEX  prop_2_f ON 合同2(档案属性) indextype is ctxsys.context  parameters('lexer my_lexer');

    4.  使用全文索引(如果对没有全文索引的列进行contains函数会报错)

    包含:

    select id from 合同2 where contains(档案属性, '测试档案属性') > 0

    不包含:

    select id from 合同2 where not contains(档案属性, '测试档案属性') > 0

    5.  删除全文索引

    drop index prop_2_f 

    6.  优化全文索引

     begin
        ctx_ddl.optimize_index('prop_2_f','full');
    END;

    4.  SQLServer全文索引用法

    1、全文索引可对char、varchar、nchar、nvarchar、text、ntext、image、xml、varbinary 或 varbinary(max) 类型字段进行检索,是解决海量数据模糊查询的好办法。

    2、一个表只能建立一个全文索引(但可以对多个字段)。

    3.  全文索引并不能达到like的效果,因为会进行分词,不一定连着的两个正好是一个词

    4.  建立全文索引的表表中必须有一个唯一性索引,并不需要是主键(建议是主键)。

      SQLServer中一个表只能有一个全文索引,索引的列可以是多列。一个全文索引目录可以对应多个表(建议最好是一对一,便于删除或者进行其他操作)。

     1.  首先开启全文索引服务

      检查服务里面带有Full-text字样的服务是否存在并开启,如果不存在带有Full-text字样的服务的,确认是否安装了sqlserverFullTextSearch

    2.  新建全文目录

    create fulltext catalog ftc_test1 with accent_sensitivity = off;

    3.建立全文索引

    (1)查看表的主键索引名称

    select convert(varchar(100), CONSTRAINT_NAME) from INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_NAME), 'IsPrimaryKey') = 1 and table_name = 'test1';

    结果:

    PK_test1

    (2)建立全文索引(创建全文索引的时候必须指定一个唯一索引,所以建议用主键索引)

    create fulltext index on test1 key index [PK_test1] on ftc_test1 with (CHANGE_TRACKING AUTO)

    (3)全文索引中添加列

    alter fulltext index on test1 add ([name] LANGUAGE [Simplified Chinese])

    (4)查看

    可以通过可视化工具查看:

     4.  使用全文索引-如果对未建立全文索引的列使用contains会报错

    包含: 名字包含梦想的

    select * from test1 where contains(name , '梦想')

    内容包含什么和结局的:

    select * from test1 where contains(content, '什么 and 结局')

    内容包含什么或结局的:

    select * from test1 where contains(content, '什么 or 结局')

    带有张*词语的

    select * from test1 where contains(name, '"张*"')

    包含韩国和首都,且这两个词紧邻

    select * from test1 where contains(content, '韩国 near 首都')

    name包含什么或者content包含什么的:

    select * from test1 where contains((name, content), '什么')

    全部索引列中查询包含结局的

    select * from test1 where contains(*, '结局')

    不包含:

    select * from test1 where not contains(name , '梦想')

    更多的语法参考:https://docs.microsoft.com/zh-cn/previous-versions/sql/sql-server-2008/ms187787(v=sql.100)

     5.  索引优化

    (1)查看全文索引目录

    select name from SYS.fulltext_catalogs

    结果:

    ftc_test1

    (2)重新优化

    alter fulltext catalog [ftc_test1] reorganize

    6.  删除索引以及相关目-删除的时候与增加的顺序相反。

    (1)从全文索引中移除

    alter fulltext index on test1 drop ([name])

    (2)  删除全文索引

    drop fulltext index on test1

    (3) 删除表

    drop table test1

    (4) 删除全文索引目录

    drop fulltext catalog  ftc_test1
  • 相关阅读:
    android中uiautomatorviewer monkeyrunner脚本地址
    python subprocess 获取执行结果
    blazor学习
    【.NET框架实战】IdentityServer4身份验证、授权
    命令行 查看当前.net和.net core版本
    github种的asp.net core源代码
    ASP.NET Core Web主机(IWebHostBuilder)
    EntityFrameworkCore教程:生成数据库表
    2021年规划
    [从0到1搭建ABP微服务]
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/11328895.html
Copyright © 2011-2022 走看看