MySQL到ES

一、 为什么非 ES 不可?(业务痛点)

在传统的 MySQL 架构中,当我们执行 WHERE title LIKE '%Java%' 时:

  1. 全表扫描:数据库必须逐行检查,查询效率随数据量增加呈线性下降。

  2. 无法分词:搜索"Java开发",MySQL 很难精准匹配到只包含"Java"或"开发"的记录。

ES 的核心价值:将搜索延迟从"秒级"降低到"毫秒级",并提供强大的相关性评分(搜索结果谁更匹配排在前面)。


二、 核心架构:像理解数据库一样理解 ES

Elasticsearch 关系型数据库 (MySQL) 说明
Index (索引) Database (数据库) 数据的逻辑容器
Type (类型) Table (表) ES 7.x 后已弱化,通常一个索引对应一类数据
Document (文档) Row (行) 最小的数据单元(JSON 格式)
Field (字段) Column (列) 数据的属性
Mapping (映射) Schema (表结构) 定义字段类型(text, keyword 等)

核心机制:分布式分片

  • Shard (分片):将一个大索引拆分成多个小块,分布在不同服务器上,实现横向扩展。

  • Replica (副本):分片的备份,保证某台服务器宕机时数据不丢失,并提升查询并发能力。


三、 必杀技:倒排索引 (Inverted Index)

这是 ES 为什么快的底层秘密。

  • 正排索引:文档 ID -> 文档内容(像看书,想找某个词得翻遍全书)。

  • 倒排索引:关键词 -> 文档 ID 列表(像查书后的索引表,直接定位页码)。

倒排索引表组成:

  1. Term Dictionary (词典):记录所有不重复的关键词。

  2. Posting List (倒排列表):记录该关键词在哪些文档出现过、出现的频率(TF)和位置。


四、 环境搭建:Linux 手动部署要点

对于 Java 全栈开发,理解 Linux 下的内核限制配置是面试常考的运维细节。

1. 核心系统配置

Bash

复制代码
# 1. 调整最大文件句柄数(ES 需要频繁读写大量小文件)
vim /etc/security/limits.conf
* soft nofile 65536
* hard nofile 65536

# 2. 调整虚拟内存限制(防止内存溢出)
vim /etc/sysctl.conf
vm.max_map_count=262144
sysctl -p

2. 关键配置 (elasticsearch.yml)

YAML

复制代码
cluster.name: my-application
node.name: node-1
network.host: 0.0.0.0       # 允许远程访问
http.port: 9200             # REST API 端口
http.cors.enabled: true      # 开启跨域,方便前端连接
http.cors.allow-origin: "*"

五、 IK 中分分词器:解决"中文搜索"

ES 自带的分词器会将中文按字拆分(如:重、头、写...),这不符合业务逻辑。

  • ik_smart:粗粒度拆分,节省空间。

  • ik_max_word:最细粒度拆分,搜索更全。

配置词典 :在 IKAnalyzer.cfg.xml 中配置 ext_dict,可以添加公司特有的专业术语(如你的项目名"Antigravity")。


六、 DSL 高级查询实战

这是你后端代码中构建查询逻辑的模版。

1. 布尔查询 (Bool Query) - 业务中最常用

JSON

复制代码
GET /order/_search
{
  "query": {
    "bool": {
      "must": [ 
        { "match": { "goods_name": "华为手机" } } 
      ],
      "filter": [ 
        { "range": { "price": { "gte": 2000, "lte": 5000 } } },
        { "term": { "status": "published" } }
      ]
    }
  }
}

面试点 :为什么用 filter

答:filter 不计算相关性评分,且有缓存机制 ,性能远高于 must


七、 Spring Boot 3.x 深度集成

现在企业主流使用的是 ElasticsearchJavaClient(替代了已过时的 High Level Client)。

1. 核心依赖

XML

复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

2. 实战:构建一个搜索 Service

Java

复制代码
@Service
public class GoodsSearchService {

    @Autowired
    private ElasticsearchClient client; // 2026年主流客户端

    public SearchResponse<Goods> searchGoods(String keyword) throws IOException {
        return client.search(s -> s
            .index("goods")
            .query(q -> q
                .bool(b -> b
                    .must(m -> m.match(t -> t.field("name").query(keyword)))
                    .filter(f -> f.term(t -> t.field("is_delete").value(0)))
                )
            ), Goods.class);
    }
}

八、 2 年经验必看的优化与面试追问

  1. 数据同步方案:MySQL 和 ES 怎么同步?

    • 方案 A (同步双写):代码中写完 MySQL 紧接着写 ES。优点是实时,缺点是耦合。

    • 方案 B (异步 MQ):MySQL 成功后发消息给 RabbitMQ,由消费者同步 ES。解耦,保证最终一致性。

    • 方案 C (Canal/CDC):监听 MySQL Binlog,全自动同步。对业务代码零侵入(大厂首选)。

  2. 深度分页问题

    • 普通的 from + size 在翻到 10000 页以后会极慢(因为要汇总所有分片数据)。

    • 对策 :使用 search_after(类似游标)来处理海量数据的连续拉取。

  3. 索引预热

    • 对于商城主页面,可以在系统启动时利用 ApplicationRunner 预先执行一次复杂查询,让 ES 将索引数据加载到操作系统的 Page Cache 中。
相关推荐
2501_901006471 小时前
MySQL主从复制过程中怎么增加从库_利用mysqldump快速扩容从库
jvm·数据库·python
2301_769340671 小时前
Navicat导出CSV文件数据为空如何解决_过滤条件与权限排查
jvm·数据库·python
kexnjdcncnxjs1 小时前
bootstrap如何设置响应式导航栏的切换宽度
jvm·数据库·python
2301_815901971 小时前
如何测试FSFO观察者进程的自动切换_模拟主库断网与Observer心跳超时
jvm·数据库·python
2401_824222691 小时前
利用 NumPy 广播机制高效实现跨维度数组减法运算
jvm·数据库·python
dinglu1030DL1 小时前
C#怎么实现Swagger文档 C#如何在ASP.NET Core中集成Swagger自动生成API文档【框架】
jvm·数据库·python
2401_846339561 小时前
如何防止邮件HTML被过滤_安全标签白名单【指南】
jvm·数据库·python
走马走马1 小时前
数据库事务
数据库
_376271531 小时前
怎样查询不同表的字段差异 information_schema结构对比
jvm·数据库·python