文章表中文章内容content字段存富文本数据,在大量数据的前提下关于优化查询速度的思考
背景:Mysql中有个文章表,文章表中有个content字段,这个字段存的是文章内容,且这个文章内容是富文本数据。这个时候面临两个问题:(假如文章表中有2000万条数据)
- 我要在文章表的content字段做模糊查询,这个会非常慢
- 普通查询非常慢
Ⅰ 关于全文检索的优化
关于全文检索的优化。现有的方式有:
- 使用Mysql全文检索。
- 使用Elasticsearch
在这种大量数据且想提高查询速度的前提下,增加ES组件比单纯使用Mysql全文索引更有效。所以有必要增加ES组件的使用。
在当前的模式下(已有2000万数据),现在最好的方式是:
- 新增 Elasticsearch,将 content 字段的全文数据同步到搜索引擎。
- 插入时:MySQL 只存储文章元数据(标题、作者、时间等),异步将 content 发送到 Elasticsearch。
- 查询时:模糊查询走 Elasticsearch,其余数据从MySQL 快速检索。
- 后期可以分库分表。单表数据过大,按时间(如按月)(如 article_202502)分表。
- 后期可以缓存层加速,高频访问的文章数据(如热门文章)缓存到 Redis。
- 后期可以升级 SSD 硬盘,低成本硬件升级可带来 30%~50% 性能提升。
Ⅱ 如果重新设计这套文章体系,应该如何设计?
Ⅰ 如何维护2000万条数据,到数据库?
- 使用消息队列。生产者上传文章可以做到快速返回。消息者端开启多个消费者进行消息消费。
- 消费者消费文章的时候,把文章异步上传到Mysql与ES,Mysql存储文章相关数据,ES存储文章数据与文章元数据。
上传细节①:文章可以使用Gzip压缩,提高传输效率.
上传细节②:图片与视频上传到Minio,记录名字,如果上传的有一致的,直接复用。
上传细节③:上传到ES的时候,需要对富文本HTML数据进行清洗,避免误查,最好多加两个字段,一个纯文本就行全局检索用,一个是富文本字段。 - 全局检索的时候,走ES。其余的走Mysql。
Ⅱ 细节方面
插入优化:
-
批量插入:减少事务开销,但用户可能是单条插入,需要确认。
-
分库分表:如果单表太大,拆分可以减少单次插入的压力。按时间或ID分表。
-
异步写入:先写入队列,再批量处理,可能降低实时性,但提高插入速度。
-
压缩content字段:比如用gzip压缩后再存储,减少存储空间,提高I/O速度。但查询时需要解压,可能增加CPU负担,需要权衡。
模糊查询优化:
- 使用全文搜索引擎,比如Elasticsearch,专门处理文本搜索,支持分词和快速查询。将content导入ES,查询时走ES。
普通查询优化:
-
确保查询字段都有合适的索引,比如主键、文章ID、时间字段等。避免全表扫描。
-
使用缓存,如Redis,缓存热点文章数据,减少数据库查询次数。
-
分库分表,减少单表数据量,提升查询效率。
-
定期归档旧数据,将历史数据移到归档库,保持主表数据量在可控范围。