解决查询慢的第一步不是盲目优化,而是找到具体的慢SQL语句。我们需要开启MySQL的慢查询日志功能,记录执行时间超过指定阈值的SQL。
登录数据库服务器,编辑MySQL配置文件my.cnf(Linux通常位于/etc/my.cnf)。在[mysqld]模块下添加或修改以下配置:
保存配置后,重启MySQL服务使配置生效:
```bash systemctl restart mysqld ```接下来,观察一段时间业务运行,然后使用mysqldumpslow工具分析日志文件,找出出现次数最多或执行时间最长的SQL:
数字档案馆系统最典型的慢查询场景是“多条件组合检索”,例如:按档案年度、保管期限、题名进行查询。单列索引无法满足此类需求,必须建立联合索引。
假设核心表为t_archives,业务查询通常如下:
使用EXPLAIN命令分析上述SQL,若发现type为ALL或index,说明进行了全表扫描。我们需要按照“最左前缀原则”建立联合索引。将区分度高的字段(等值查询字段)放在前面,范围查询或模糊查询字段放在后面:
注意:对于LIKE '%...'(前置模糊匹配),索引无法生效。如果业务必须进行全模糊检索,建议引入Elasticsearch(详见第五步)。如果仅是后缀模糊LIKE '...%',上述索引可以生效。
档案列表页翻页到几十万页时,传统的LIMIT offset, size性能会急剧下降,因为数据库需要扫描offset行数据再丢弃。我们需要改写SQL,利用覆盖索引进行“延迟关联”。
低效写法(扫描1000100行):
```sql SELECT FROM t_archives ORDER BY id LIMIT 1000000, 10; ```高效优化方案(利用子查询先定位ID):
```sql SELECT t1. FROM t_archives t1 INNER JOIN ( SELECT id FROM t_archives ORDER BY id LIMIT 1000000, 10 ) t2 ON t1.id = t2.id; ```优化原理:子查询只查询ID列,可以使用覆盖索引,在内存中快速定位到对应的100万个ID的位置,然后通过关联查询回表取出完整数据。这种写法在大数据量下可以将查询时间从秒级降低到毫秒级。

档案系统的“首页统计”、“热门档案详情”等高频访问数据,不应该每次都击穿数据库。使用Redis缓存这些热点数据是提升并发能力的最快手段。
1. 安装Redis:
```bash 使用Docker快速部署 docker run -d -p 6379:6379 --name redis-cache redis:7-alpine ```2. 业务代码逻辑改造(伪代码示例):
在获取档案详情的Service层增加缓存逻辑:
```python import redis 连接Redis r = redis.Redis(host='127.0.0.1', port=6379, db=0) def get_archive_detail(archive_id): 1. 构造缓存Key cache_key = f"archive:detail:{archive_id}" 2. 尝试从Redis获取 data = r.get(cache_key) if data: return data.decode('utf-8') 3. Redis未命中,查询数据库 注意:这里要防止缓存击穿,建议加互斥锁或使用双重检查锁定 sql = "SELECT FROM t_archives WHERE id = %s" db_result = execute_db_query(sql, (archive_id,)) if db_result: 4. 将结果写入Redis,设置过期时间为1小时 r.setex(cache_key, 3600, serialize(db_result)) return db_result return None ```关键点:必须设置合理的过期时间(TTL),防止数据不一致;同时对于写入操作,要采用“先更新库,再删除缓存”的策略,保证数据最终一致性。
数字档案馆的核心需求是全文检索(OCR识别后的文本内容检索)。MySQL的LIKE查询在大文本量下无力支撑,必须引入Elasticsearch。
1. 部署Elasticsearch:
```bash docker run -d \ --name es-node \ -p 9200:9200 \ -e "discovery.type=single-node" \ -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \ elasticsearch:8.11.0 ```2. 创建索引(Mapping):
我们需要定义分词器,对中文内容进行精准分词。发送PUT请求到http://localhost:9200/archives_index:
3. 数据同步与查询:
在业务代码中,当档案产生或更新时,异步写入ES。查询时,直接请求ES:
```json GET /archives_index/_search { "query": { "bool": { "must": [ { "match": { "content": "合同纠纷" } }, { "range": { "create_time": { "gte": "2023-01-01" } } } ] } } } ```通过ES替代MySQL进行复杂文本检索,可以将千万级数据量的检索响应时间控制在100毫秒以内。实施时需注意维护MySQL与ES的数据一致性,通常建议使用Canal或Debezium监听MySQL Binlog进行增量同步。