AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 312517
Accepted
Blackbam
Blackbam
Asked: 2022-05-25 06:01:46 +0800 CST2022-05-25 06:01:46 +0800 CST 2022-05-25 06:01:46 +0800 CST

在大型 MySQL 生产数据库中使用前导通配符进行 LIKE 查询

  • 772

根据 Amazon RDS 中的见解,大型 MySQL 生产数据库中的以下查询导致高负载(约 50.000.000 个条目):

SELECT * FROM entities WHERE status='ready' AND user_id='81663729'  AND (primary_name LIKE '%mysearch%' OR additional_names LIKE '%mysearch%')  ORDER BY id DESC  LIMIT 0, 100000

负责它的列:

common_name: VARCHAR(255) Additional_names: VARCHAR(2000) (注意:不幸的是,这是一个逗号分隔的字符串,每个条目包含零到数百个名称,这是可怕的数据库设计)

这个查询表现不佳并不奇怪:前导通配符使索引或多或少不可用(primary_name被索引,additional_names不是)。一些用户在这个表中有很多条目(目前每个用户最多有 2.000.000 个条目,条目数量正在增长) - 所以查询中的 user_id 不会挽救它的性能。

我的问题是什么可能是解决这个问题的最佳方法。

方法一:MySQL FULLTEXT 索引

创建全文索引:

CREATE FULLTEXT INDEX domain ON entities (primary_name,additional_names);

新查询:

SELECT * FROM entities WHERE status='ready' AND user_id='81663729'  AND MATCH (primary_name,additional_names) AGAINST ('mysearch') IN NATURAL LANGUAGE MODE ORDER BY id DESC  LIMIT 0, 100000;

Pro:最容易迁移和实施?

反对:不确定这是否符合要求?创建该索引可能需要大量时间。

方法二:MySQL JSON

第 1 步:使用 JSON 添加附加列

ALTER TABLE entities ADD additional_names_j JSON AFTER additional_names;

第 2 步:所有新实体都作为 json 插入到新的 JSON 列以及旧列中。

第 3 步:可能会运行几天的脚本确保所有旧实体在 JSON 列中都有其条目。

第 4 步:调整应用程序以使用 JSON 列。

第 5 步:删除旧的附加名称列。

询问:SELECT * FROM entities WHERE status='ready' AND user_id='81663729' AND 'mysearch' member of ORDER BY id DESC LIMIT 0, 100000;

优点:搜索 JSON 会更好,并且可以在没有逗号爆炸之类的情况下提取名称。

反对:不确定是否可以对 JSON 列进行部分匹配?此外,努力是相当高的。

方法 3:创建关系表和名称表

这基本上意味着我们有一个带有 id 和 name 的表和 am:n 关系表。

优点:将是漂亮和干净的设计。

Contra:必须与正在运行的应用程序并行存在并填充,在这种情况下,它将导致应用程序逻辑发生巨大变化。

我向专家提出的问题是:哪些方法能最好地解决这种情况——为什么?

注意:该表以每秒约 5 个条目的速度增长,不允许停机。我愿意接受任何其他方法来使这个查询更快,我目前不知道!

mysql query-performance
  • 1 1 个回答
  • 127 Views

1 个回答

  • Voted
  1. Best Answer
    Bill Karwin
    2022-05-25T07:45:15+08:002022-05-25T07:45:15+08:00

    方法 1:全文索引不能完成LIKE条件所能做的所有事情。我看到阻止使用全文的最常见问题是 MySQL 的实现只索引整个单词,所以如果您的搜索是部分单词,它将无济于事。

    创建索引需要时间,但如果避免停机很重要,您绝对应该熟悉使用pt-online-schema-change或gh-ost。这些都是免费工具,允许更改架构(包括添加索引),同时不会阻止客户端使用表。我们在上一份工作中使用 pt-osc 在高峰时段每周运行数百次模式更改。

    方法 2:单独添加 JSON 列将无济于事,无需为要搜索的表达式创建索引。你之前在 MySQL 中使用过 JSON 吗?在您决定之前,您应该对您使用的 MySQL 版本进行概念验证,看看它是否有效。在 MySQL 中使用 JSON 有很多限制和注意事项。我通常建议不要使用 JSON。

    进一步阅读:

    • https://dev.mysql.com/doc/refman/8.0/en/json.html
    • https://dev.mysql.com/doc/refman/8.0/en/json-functions.html
    • https://dev.mysql.com/doc/refman/8.0/en/create-table-secondary-indexes.html#json-column-indirect-index
    • https://dev.mysql.com/doc/refman/8.0/en/create-index.html#create-index-multi-valued

    方法 3:这也称为倒排索引。它可以很好地工作,但是正如您所说,它需要一些工作来维护倒排索引,在添加数据时添加值。上面的评论建议使用触发器,它确实有效,但认为这也算作添加更多代码。

    这些方法中的哪一种能最好地解决这种情况?

    如果全文索引满足您需要支持的搜索需求,我更喜欢全文索引。优点是维护索引所需的代码最少,这是一个很大的优势。

    但每次我听到“哪个最好?”的问题时。我知道这是个错误的问题。没有适用于所有情况的“最佳”解决方案。您的项目有自己的要求,您需要选择适合这些要求的解决方案。任何解决方案都可能最适合一个人的应用程序,但不适用于另一个应用程序。

    • 1

相关问题

  • 是否有任何 MySQL 基准测试工具?[关闭]

  • 我在哪里可以找到mysql慢日志?

  • 如何优化大型数据库的 mysqldump?

  • 什么时候是使用 MariaDB 而不是 MySQL 的合适时机,为什么?

  • 组如何跟踪数据库架构更改?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve