V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
shyrock
V2EX  ›  MySQL

MySQL 的 like %关键字怎么优化?

  •  
  •   shyrock · 2014-09-17 15:29:39 +08:00 · 33876 次点击
    这是一个创建于 3699 天前的主题,其中的信息可能已经有所发展或是发生改变。
    为了降低成本,打算把现有系统从Oracle迁移到MySQL。
    但是偶然听到用过的人抱怨MySQL对于like %关键字 这种查询条件没法使用索引,都是全表扫描。
    很担心移植后的性能。

    各位知道怎么优化吗?
    35 条回复    2020-02-26 18:02:26 +08:00
    happywowwow
        1
    happywowwow  
       2014-09-17 15:47:48 +08:00   ❤️ 1
    昨天刚好看到 match()against 你可以去看看? 我也不是很懂,看见代码里有人这么写的,去搜了下,说是比like好
    mengzhuo
        2
    mengzhuo  
       2014-09-17 15:53:16 +08:00   ❤️ 1
    5.5以后支持了FullText Search
    em70
        3
    em70  
       2014-09-17 15:58:25 +08:00   ❤️ 1
    看你数据有多大的量,量不大,like就足够了,如果很大量就不能单纯依靠数据库,要用搜索引擎技术,先对内容做分词处理,建立反向索引,存到数据库.这会占用大量的空间,但查询速度和精度可以大大提高. 计算机永远是时间换空间,空间换时间的游戏
    nilai
        4
    nilai  
       2014-09-17 16:00:07 +08:00   ❤️ 1
    sphinx
    shyrock
        5
    shyrock  
    OP
       2014-09-17 16:22:07 +08:00
    @happywowwow
    @mengzhuo
    @em70
    你们说的都是全文检索吧,
    问题是建立的全文检索索引后,我理解只能匹配整词的输入条件,但是对于想用‘%ord'搜索到’Word‘的情况能match against到吗?
    shyrock
        6
    shyrock  
    OP
       2014-09-17 16:23:19 +08:00
    @em70 量大约是10w到100w记录级别,我理解全表扫面已经不可接受了。
    love
        7
    love  
       2014-09-17 16:24:11 +08:00
    @shyrock 难道oracle对于通配符在前的like能利用索引?
    Livid
        8
    Livid  
    MOD
       2014-09-17 16:24:37 +08:00   ❤️ 1
    或许你们可以考虑单独用 ElasticSearch 做一个搜索的 service:

    http://www.elasticsearch.org/
    davepkxxx
        9
    davepkxxx  
       2014-09-17 16:28:58 +08:00
    数据量大的花使用全文检索系统代替like
    qsun
        10
    qsun  
       2014-09-17 16:38:00 +08:00   ❤️ 1
    我知道我下面说的会被人喷,但是我还是要说:

    就10万100万的数据,如果是考虑性能的话,根本不用 sphinx/elasticsearch 这种 full-text search engine。尽量让数据保持热度就可以了。

    如果用了 sphinx/elasticsearch,还需要重新考虑各种过滤。
    shyrock
        11
    shyrock  
    OP
       2014-09-17 16:42:14 +08:00
    @love 据说可以加反向索引来解决,这个链接提到了,但是语焉不详: http://www.kuqin.com/database/20120207/317909.html
    我又搜到另外一篇,比较靠谱,是建立function index + reverse的方式:
    http://jeffkemponoracle.com/2008/01/17/like-with-wildcard-at-start-can-use-an-index/
    shyrock
        12
    shyrock  
    OP
       2014-09-17 16:50:11 +08:00
    @Livid 看了一下,elasticsearch是基于lucene的吧,实际上我们的系统中已经基于lucene搭了个全文检索。但是不能支持非整词匹配的模糊查询是个问题。
    shyrock
        13
    shyrock  
    OP
       2014-09-17 16:50:48 +08:00
    @davepkxxx 同上,全文检索无法完全覆盖需求。模糊查询是问题。
    shyrock
        14
    shyrock  
    OP
       2014-09-17 16:52:14 +08:00
    @qsun 100w级别的数据,保持热度的意思是全部放到内存中吗?我不清楚缓存中100w级别的全表扫描是什么性能。
    davepkxxx
        15
    davepkxxx  
       2014-09-17 17:40:53 +08:00
    @shyrock 你用的中文词库不支持自己增加词组?
    davepkxxx
        16
    davepkxxx  
       2014-09-17 17:43:00 +08:00
    @shyrock 啊,想到问题在哪里了,上一句话当我没说。
    em70
        17
    em70  
       2014-09-17 20:08:09 +08:00
    @shyrock 被检索字段数据量有多少,如果只是255以内,几十万的记录like问题应该也不大,服务器内存大点就OK了,100万以上,还是考虑反向索引吧,like不适合
    20150517
        18
    20150517  
       2014-09-17 20:17:09 +08:00 via Android   ❤️ 1
    @shyrock 100万全表ssd 上cluster index扫描大约10秒内
    em70
        19
    em70  
       2014-09-17 20:29:13 +08:00   ❤️ 2
    @shyrock 反向索引的意思是,把一段文本里的每个词都与原文建立对应关系,也就是说,一段文字有100个单词,那么需要创建100条记录,搜索的时候不搜索原文,在这100个记录里面查找,有匹配就说明原文里有这个单词,这100个记录建立索引查找就很快

    谷歌百度他们,不光词做反向索引,还把多个连续词一起索引,甚至一句话也索引,一个网页可能建立几十万个反向索引,索引库可能几百亿,上千亿,实时搜索还是慢,这时他们还用了缓存技术,提前把可能搜到的词的搜索结果计算出来保存
    zyx89513
        20
    zyx89513  
       2014-09-17 23:03:58 +08:00
    @nilai 最近在比较sphinx和elasticsearch, 可以介绍下经验吗?
    88250
        21
    88250  
       2014-09-17 23:06:10 +08:00
    @Livid 可惜 es 的脑裂问题至今未解决
    cloudzhou
        22
    cloudzhou  
       2014-09-17 23:18:41 +08:00
    如果对 lucene 比较熟悉,可以直接使用 lucene 来做
    GTim
        23
    GTim  
       2014-09-17 23:25:04 +08:00
    谁说like %关键字 没法用索引的,是like %关键字% 没法用索引
    pubby
        24
    pubby  
       2014-09-17 23:27:45 +08:00   ❤️ 1
    @zyx89513 中文么?sphinx中文版 coreseek新版一直难产

    老版本不支持线程,索引大的话建议切分用到多个coreseek进程来服务
    zyx89513
        25
    zyx89513  
       2014-09-17 23:52:55 +08:00
    @pubby 是啊中文, 那个coreseek我看了好像很久没更新了一样。 所以你觉得还是elasticsearch好一些是么? 我看有个插件elasticsearch-river-jdbc可以配合 MySQL 一起使用
    GTim
        26
    GTim  
       2014-09-18 00:01:10 +08:00
    @GTim 我错了. 不能用到索引
    pubby
        27
    pubby  
       2014-09-18 00:44:36 +08:00   ❤️ 1
    @zyx89513 没用过lucence系的,不好比较。
    我是用xml数据源,没有mysql配合,勉强够用
    shyrock
        28
    shyrock  
    OP
       2014-09-18 10:00:09 +08:00
    @em70 可惜还是不能满足我说的部分词匹配的要求啊。。。总不能把Word拆分成W/ord来建索引吧
    6711411
        29
    6711411  
       2014-09-18 10:55:05 +08:00
    有人使用过 sphinx 做地理位置搜索吗? 有的话请回复我一下, 有问题请教...
    halfelf
        30
    halfelf  
       2014-09-18 11:11:33 +08:00
    es做regex filter显然可以解决这个问题
    em70
        31
    em70  
       2014-09-18 12:24:37 +08:00
    @shyrock 这需要一些优化技巧,首先单词就那几千个,可以先在单词表like搜索,找到最可能匹配的单词,然后用这个单词再去反向索引库搜索
    shyrock
        32
    shyrock  
    OP
       2014-09-18 16:51:13 +08:00
    @halfelf 愿闻其详
    RangerWolf
        33
    RangerWolf  
       2014-09-19 09:27:58 +08:00
    AWS DynamoDB 便宜好用~ 而且非常非常的diao
    100W的数据,查询延迟还是能做到毫秒的级别,而且不需要你去关心底层如何优化。如果全套托管在AWS的话,WebApp放Elastic Beanstalk。 每个月不会超过10$的费用。甚至连10¥都不一定需要。注意:导入数据到DynamoDB是免费的! 流量不花钱。

    AWS的问题就是服务太多了,不熟悉的情况下不知道哪个合适自己。。。。

    刚用上AWS,发现太赞了,所以强烈推荐。
    RangerWolf
        34
    RangerWolf  
       2014-09-19 09:29:31 +08:00
    @shyrock 关于你要查询W/ord 这种需求。感觉就需要你针对业务去仔细设计一下DB的结构了。 Good luck 哈哈
    RyanArthur
        35
    RyanArthur  
       2020-02-26 18:02:26 +08:00
    如果有同学查到这里,我要为大家填一个坑,FTS ( FullText Search) 的使用与 InnoDB 和 MyIASM 有关系。如果使用 InnoDB,那么如果查询的关键字小于 innodb_ft_min_token_size 的约定或者大于 innodb_ft_max_token_size 的约定值,那么 FTS 会直接忽略查询结果。如果使用 MyIASM,是 ft_min_token_size 和 ft_max_token_size。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   918 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 21:31 · PVG 05:31 · LAX 14:31 · JFK 17:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.