sql处理千万数据查询缓慢问题

Posted yanchaohui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sql处理千万数据查询缓慢问题相关的知识,希望对你有一定的参考价值。

给需要查询的字段增加全文索引

ALTER TABLE 表名 ADD FULLTEXT ( `字段`)

增加完全文索引后如下sql

SELECT * FROM `表名` WHERE MATCH(加了索引字段) AGAINST (查询内容 IN BOOLEAN MODE)

全文索引分三种模式:

一、自然语言查找。这是mysql默认的全文搜索方式

select  id,title FROM post WHERE MATCH(content) AGAINST (search keyword)


或者显式声明使用自然语言搜索方式

 select  id,title FROM post WHERE MATCH(content) AGAINST (search keyword IN NATURAL LANGUAGE MODE)

 

由于自然语言搜索方式是默认模式,所以可以省略声明模式的“IN NATURAL LANGUAGE MODE”部分。
自然语言搜索模式的么特点:

    1.忽略停词(stopword),英语中频繁出现的and/or/to等词被认为是没有实际搜索的意义,搜索这些不会获得任何结果。
    2.如果某个词在数据集中频繁出现的几率超过了50%,也会被认为是停词,所以如果数据库中只有一行数据,不管你怎么全文搜索都不能获得结果。
    3.搜索结果都具有一个相关度的数据,返回结果自动按相关度由高到低排列。
    4.只针对独立的单词进行检索,而不考虑单词的局部匹配,如搜索box时,就不会将boxing作为检索目标。


二、布尔查找。这种查找方式的特点是没有自然查找模式中的50%规则,即便有词语在数据集中频繁出现的几率超过50%,也会被作为搜索目标进行检索并返回结果,而且检索时单词的局部匹配也会被作为目标进行检索。sql示例

select  id,title FROM post WHERE MATCH(content) AGAINST (search keyword IN BOOLEAN MODE)


三、带子查询扩展的自然语言查找。 

select  id,title FROM post WHERE MATCH(content) AGAINST (search keyword IN BOOLEAN MODE WITH EXPANSION)

暂时没有明白这种模式。

 

四、布尔全文搜索支持以下操作符:

    " + "  一个前导的加号表示该单词必须 出现在返回的每一行的开头位置
    " - " 一个前导的减号表示该单词一定不能出现在任何返回的行中
    (无操作符) 在默认状态下(当没有指定 + 或–的情况下),该单词可有可无,但含有该单词的行等级较高。这和MATCH() ... AGAINST()不使用IN BOOLEAN MODE修改程序时的运作很类似
    " > < "这两个操作符用来改变一个单词对赋予某一行的相关值的影响。 >操作符增强其影响,而 <操作符则减弱其影响。请参见下面的例子
    " () "括号用来将单词分成子表达式。括入括号的部分可以被嵌套
    " ~ "一个前导的代字号用作否定符, 用来否定单词对该行相关性的影响。 这对于标记“noise(无用信息)”的单词很有用。包含这类单词的行较其它行等级低,但因其可能会和-号同时使用,因而不会在任何时候都派出所有无用信息行
    " * "星号用作截断符。于其它符号不同的是,它应当被追加到要截断的词上
    " " "一个被括入双引号的短语 (‘"’) 只和字面上包含该短语输入格式的行进行匹配。全文引擎将短语拆分成单词,在FULLTEXT索引中搜索该单词。  非单词字符不需要严密的匹配:短语搜索只要求符合搜索短语包含的单词且单词的排列顺序相同的内容。例如, "test phrase" 符合 "test, phrase"。
    "configured database "寻找包含至少两个单词中的一个的行
    " +configured +database "寻找两个单词都包含的行
    " +configured database "寻找包含单词“"configured”的行,若这些行也包含单词“"database”, 则列为更高等级
    " +configured -database "寻找包含单词“configured” 但不包含单词 “database”的行
    " +configured +(>database<sql) "寻找包含单词“configured”和“database” 的行,或包含“configured” 和“sql”的行 (无先后顺序),然而包含 “configured database”的行较包含“configured sql”的行排列等级更为高
    " mysql* "寻找包含"mysql"或有"mysql"开头单词的行
    " “my sql” "寻找包含原短语“my sql”的行

 

如:

select * from info where match(title,info) against("+mysql -yoursql" in boolean mode);
select * from info where match(title,info) against(+configured +database);

 

在我的实际使用中还发现了以下细节:
1、只有MyISAM表支持
    2、对大多数的多字节字符集适用,进行全文索引的列必须使用相同的字符集和校验码(collation)。
    3、表意性语言,如汉语、日语没有词分界符(英语用空格隔开每个单词),全文分析器无法确定一个词的开始和结尾,所以MySQL中的全文检索不支持。
    4、在自然语言检索中,只能检索被全文索引的那些列,如果要对索引的多列进行某一列的检索,必须对这一列单独建立全文索引。布尔检索可以在非索引的列上进行,但会慢一些。
    5、against后的参数必须是常量字符串。
    6、索引没有记录关键词在字符串中的位置,排序算法太单一。
    7、如果索引不在内存中,检索速度会很慢;如果是短语查询,需要索引和数据都在内存中,否则速度会很慢,所以需要更大的key buffer。索引有碎片时也会很慢,所以需要更频繁的optimize table操作。
    8、全文索引对于insert、update、delete都很慢。如更改100个词需要进行100次的索引操作而不是1次。
    9.布尔查找时必须指定返回结果的排序方式,它不会像自然语言查找那样会自动将结果按相关度排序返回。
    10.即使是布尔查找,对长度小于等于3的单词也不会进行检索,因为mysql有一个系统变量FT_MIN_WORD_LEN指定了全文检索时可接受的最小单词长度,默认值是4。

以上是关于sql处理千万数据查询缓慢问题的主要内容,如果未能解决你的问题,请参考以下文章

mysql千万级数据量查询出所有重复的记录

第1章 高效处理千万数据

如何解决SQL Server查询速度缓慢的问题

如何解决SQL Server查询速度缓慢的问题

如何解决SQL Server查询速度缓慢的问题

运行缓慢的 SQL 查询