博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
全文索引 与 Like 的实现原理
阅读量:7217 次
发布时间:2019-06-29

本文共 2256 字,大约阅读时间需要 7 分钟。

在数据库使用中,DBA都会告诉大家SQL的LIKE条件为%XXX%号时,由于不能使用索引,当数据量变大时(比如超过百万条),全表扫描会导致性能很差。

  但是在实际业务中,很难避免MySQL全文检索并Like索引的这种需求。比如模糊搜索用户帐号,昵称之类。既然这个需求必须做,但又不可以直接用LIKE。这里我和大家分享一下我们关于这种需求的一种解决方案。当然别人也可能采用过类似的办法,我不是很清楚。所以也用一下“原创”吧。

  MySQL数据库很早就支持全文索引,但是全文索引和LIKE语句是不同的。具体点说,全文索引的单位是词,耳LIKE匹配的是字符。当然实际的区别更大,比如“老鼠爱大米”这段文本用全文搜索的话,条件“老鼠爱大米”,“老鼠和大米”,“大米老鼠”,“大米与老鼠”会搜索到内容,但是“爱”,“鼠爱”,“爱大”不会搜索到内容。反之,使用LIKE搜索时,“老鼠和大米”,“大米老鼠”,“大米与老鼠”不会找到内容,而“爱”,“鼠爱”,“爱大”会找到内容。我们这里不讨论两种方式的优劣,根据实际情况每种功能都会有各自的实际需求。比如对于大段文本,全文检索是最好的方法,但是对于姓名,帐号,昵称等很短的通常无意义文本,LIKE会更合适一些。

  虽然全文检索和LIKE搜索不同,但是在特殊情况下,可以用全文搜索功能来实现LIKE搜索。具体就是每个字符作为一个词,而且使用双引号来限制词精确匹配(简单点说就是老鼠大米和大米老鼠不同),这样可以实现LIKE搜索的功能。

  下面还是说一下具体的做法吧。

  首先,数据库指定 --ft_min_word_len=2 --ft_stopword_file=""。第一个参数是告诉数据库,小于2个字符的词忽略。第二个是告诉数据库不忽略任何特殊词。这些设置是给实现功能创造条件。

  然后建搜索表

  CREATE TABLE tbl_search (

  id int(10) unsigned NOT NULL auto_increment,

  name varchar(500),

  PRIMARY KEY (id),

  FULLTEXT KEY idx_name (name)

  ) ENGINE=MyISAM AUTO_INCREMENT=1;

  static String encode(String input) {

  if (input == null) return null;

  StringBuilder output = new StringBuilder();

  for (int i = 0, c = input.length(); i < c; ++i) {

  char ch = input.charAt(i);

  if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z'

  || ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z'

  || ch == '_' || ch == '-') {

  output.append(Integer.toHexString(ch)).append(' ');

  } else if (ch >= 'a' && ch <= 'z' || ch >= 'a' && ch <= 'z') {

  output.append(Integer.toHexString((int)ch - 32)).append(' ');

  } else {

  Character.UnicodeBlock block = Character.UnicodeBlock.of(ch);

  if (block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS

  || block == Character.UnicodeBlock.KATAKANA

  || block == Character.UnicodeBlock.HIRAGANA) {

  output.append(Integer.toHexString(ch)).append(' ');

  } else {

  // do nothing

  }

  }

  }

  // trim blank

  int last = output.length() - 1;

  if (last > 0 && output.charAt(last) == ' ') {

  output.deleteCharAt(last);

  }

  return output.toString();

  }

  使用上面的代码对要搜索的内容编码,比如内容是“蓝皮鼠2008”,编码后的结果是“84dd 76ae 9f20 32 30 30 38”。将编码后的内容存入name字段。

  使用如下SQL语句进行搜索

  select * from tbl_search where match(name) against('"76ae 9f20 32"' in boolean mode)

  这样就基本实现了MySQL全文检索中的Like索引。

转自:

转载于:https://www.cnblogs.com/bobsoft/archive/2012/10/07/2714545.html

你可能感兴趣的文章
数据结构-栈的实现之行编译器核心实现
查看>>
C++ Project 积累(2)
查看>>
(1)用VisualSvn Server,Tortoise Svn,AnkhSvn搭建Svn版本控制
查看>>
Mysql索引
查看>>
格式化输出
查看>>
hdu 3804 Query on a tree (树链剖分+线段树)
查看>>
定位、指南针、地理编码
查看>>
Kafka 简介
查看>>
MySQL 用户连接与用户线程
查看>>
RabbitMq、ActiveMq、Kafka和Redis做Mq对比
查看>>
C# 图片处理(压缩、剪裁,转换,优化)
查看>>
Linux bridge-utils tunctl 使用
查看>>
Leetcode Pascal&#39;s Triangle II
查看>>
运行shell脚本报错 &#39;\357\273\277&#39;: command not found 解决的方法
查看>>
android studio 0.8.1使用和遇到问题解决
查看>>
云服务器ECS选购集锦之六区域选择帮助
查看>>
云虚机选购指南之二云虚拟主机试用帮助文档
查看>>
女友眼中的IT男
查看>>
Excel连接
查看>>
java基础-多线程学习
查看>>