› 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 · Sep 17, 2014 · 35224 views
    This topic created in 4395 days ago, the information mentioned may be changed or developed.
    为了降低成本,打算把现有系统从Oracle迁移到MySQL。
    但是偶然听到用过的人抱怨MySQL对于like %关键字 这种查询条件没法使用索引,都是全表扫描。
    很担心移植后的性能。

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

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

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

    如果用了 sphinx/elasticsearch,还需要重新考虑各种过滤。
    shyrock
        11
    shyrock  
    OP
       Sep 17, 2014
    @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
       Sep 17, 2014
    @Livid 看了一下,elasticsearch是基于lucene的吧,实际上我们的系统中已经基于lucene搭了个全文检索。但是不能支持非整词匹配的模糊查询是个问题。
    shyrock
        13
    shyrock  
    OP
       Sep 17, 2014
    @davepkxxx 同上,全文检索无法完全覆盖需求。模糊查询是问题。
    shyrock
        14
    shyrock  
    OP
       Sep 17, 2014
    @qsun 100w级别的数据,保持热度的意思是全部放到内存中吗?我不清楚缓存中100w级别的全表扫描是什么性能。
    davepkxxx
        15
    davepkxxx  
       Sep 17, 2014
    @shyrock 你用的中文词库不支持自己增加词组?
    davepkxxx
        16
    davepkxxx  
       Sep 17, 2014
    @shyrock 啊,想到问题在哪里了,上一句话当我没说。
    em70
        17
    em70  
       Sep 17, 2014
    @shyrock 被检索字段数据量有多少,如果只是255以内,几十万的记录like问题应该也不大,服务器内存大点就OK了,100万以上,还是考虑反向索引吧,like不适合
    20150517
        18
    20150517  
       Sep 17, 2014 via Android   ❤️ 1
    @shyrock 100万全表ssd 上cluster index扫描大约10秒内
    em70
        19
    em70  
       Sep 17, 2014   ❤️ 2
    @shyrock 反向索引的意思是,把一段文本里的每个词都与原文建立对应关系,也就是说,一段文字有100个单词,那么需要创建100条记录,搜索的时候不搜索原文,在这100个记录里面查找,有匹配就说明原文里有这个单词,这100个记录建立索引查找就很快

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

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

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

    刚用上AWS,发现太赞了,所以强烈推荐。
    RangerWolf
        34
    RangerWolf  
       Sep 19, 2014
    @shyrock 关于你要查询W/ord 这种需求。感觉就需要你针对业务去仔细设计一下DB的结构了。 Good luck 哈哈
    RyanArthur
        35
    RyanArthur  
       Feb 26, 2020
    如果有同学查到这里,我要为大家填一个坑,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。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2698 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 67ms · UTC 14:55 · PVG 22:55 · LAX 07:55 · JFK 10:55
    ♥ Do have faith in what you're doing.