Skip to content

数据库架构与优化

1. 数据库架构模式

1.1 集群模式

集群模式通过多个数据库节点协同工作,提供高可用性和负载均衡。

优点:

  • 高可用性:节点故障时自动切换
  • 负载均衡:分散读写压力
  • 水平扩展:通过添加节点提升性能

常见实现:

  • MySQL Group Replication
  • PostgreSQL Patroni
  • MongoDB Replica Set

1.2 读写分离模式

读写分离通过主从复制,将读操作分发到从库,写操作在主库执行。

text
┌─────────┐
│  应用   │
└────┬────┘

     ├──────写──────► 主库 (Master)
     │                  │
     │                  │ 复制
     │                  ▼
     └──────读──────► 从库 (Slave 1)

                       └──────► 从库 (Slave 2)

优点:

  • 提升读性能
  • 减轻主库压力
  • 数据备份

注意事项:

  • 主从延迟问题
  • 数据一致性保证

1.3 分片模式

分片(Sharding)将数据分散存储到多个数据库实例中。

1.3.1 哈希分片

使用哈希函数将数据均匀分布到不同分片。

一致性哈希(Consistent Hashing):

  • 减少数据迁移
  • 适合节点动态增减
  • 虚拟节点提升均衡性
python
import hashlib

def consistent_hash(key, num_shards):
    """一致性哈希示例"""
    hash_value = int(hashlib.md5(key.encode()).hexdigest(), 16)
    return hash_value % num_shards

# 示例
user_id = "user123"
shard_id = consistent_hash(user_id, 4)
print(f"User {user_id} -> Shard {shard_id}")

取模哈希(Modulo Hashing):

  • 实现简单
  • 固定分片数量
  • 扩容时需要重新分配
python
def modulo_hash(key, num_shards):
    """取模哈希示例"""
    return hash(key) % num_shards

1.3.2 范围分片

按照数据范围(如 ID、时间)将数据分配到不同分片。

优点:

  • 范围查询高效
  • 数据有序性

缺点:

  • 可能出现热点问题
  • 负载不均衡

2. MySQL 优化

2.1 索引优化

MAX() 和 MIN() 函数与索引利用

在使用 MAX()MIN() 函数时,合理使用索引可以显著提升性能。

sql
-- 创建索引
CREATE INDEX idx_created_at ON users(created_at);

-- 高效查询最大值
SELECT MAX(created_at) FROM users;

-- 高效查询最小值
SELECT MIN(created_at) FROM users;

参考:MySQL 之查询:max() 和 min() 函数与索引利用

2.2 查询优化

使用 EXPLAIN 分析查询

sql
EXPLAIN SELECT * FROM users WHERE age > 18;

关键字段说明:

  • type:访问类型(ALL, index, range, ref, eq_ref, const)
  • key:实际使用的索引
  • rows:扫描的行数
  • Extra:额外信息

避免全表扫描

sql
-- 不好的查询
SELECT * FROM users WHERE YEAR(created_at) = 2024;

-- 优化后的查询
SELECT * FROM users WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01';

2.3 连接池配置

合理配置连接池可以提升数据库性能:

python
import pymysql
from dbutils.pooled_db import PooledDB

# 创建连接池
pool = PooledDB(
    creator=pymysql,
    maxconnections=20,  # 最大连接数
    mincached=2,        # 最小空闲连接
    maxcached=5,        # 最大空闲连接
    blocking=True,      # 连接不足时阻塞
    host='localhost',
    user='root',
    password='password',
    database='mydb',
    charset='utf8mb4'
)

# 使用连接
conn = pool.connection()
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
results = cursor.fetchall()
cursor.close()
conn.close()

3. PostgreSQL 优化

3.1 VACUUM 和 ANALYZE

定期运行 VACUUM 和 ANALYZE 保持数据库性能:

sql
-- 清理死元组
VACUUM users;

-- 更新统计信息
ANALYZE users;

-- 完整清理和分析
VACUUM ANALYZE users;

-- 自动清理所有表
VACUUM ANALYZE;

3.2 分区表

使用分区表优化大表查询:

sql
-- 创建分区表
CREATE TABLE orders (
    id SERIAL,
    order_date DATE NOT NULL,
    amount DECIMAL(10, 2)
) PARTITION BY RANGE (order_date);

-- 创建分区
CREATE TABLE orders_2024_q1 PARTITION OF orders
    FOR VALUES FROM ('2024-01-01') TO ('2024-04-01');

CREATE TABLE orders_2024_q2 PARTITION OF orders
    FOR VALUES FROM ('2024-04-01') TO ('2024-07-01');

4. MongoDB 优化

4.1 索引策略

javascript
// 创建单字段索引
db.users.createIndex({ email: 1 })

// 创建复合索引
db.users.createIndex({ age: 1, name: 1 })

// 创建唯一索引
db.users.createIndex({ username: 1 }, { unique: true })

// 创建文本索引
db.posts.createIndex({ content: "text" })

// 查看索引使用情况
db.users.find({ email: "test@example.com" }).explain("executionStats")

4.2 聚合优化

使用聚合管道优化复杂查询:

javascript
db.orders.aggregate([
    // 过滤
    { $match: { status: "completed" } },
    
    // 分组统计
    { $group: {
        _id: "$user_id",
        total_amount: { $sum: "$amount" },
        order_count: { $sum: 1 }
    }},
    
    // 排序
    { $sort: { total_amount: -1 } },
    
    // 限制结果
    { $limit: 10 }
])

5. SQLite 优化

5.1 WAL 模式

启用 WAL(Write-Ahead Logging)模式提升并发性能:

python
import sqlite3

conn = sqlite3.connect('database.db')
conn.execute('PRAGMA journal_mode=WAL')
conn.commit()

WAL 模式优点:

  • 读写不互斥
  • 提升并发性能
  • 减少磁盘 I/O

5.2 批量插入优化

python
import sqlite3

conn = sqlite3.connect('database.db')
cursor = conn.cursor()

# 使用事务批量插入
cursor.execute('BEGIN TRANSACTION')
for i in range(10000):
    cursor.execute('INSERT INTO users (name, age) VALUES (?, ?)', 
                   (f'User{i}', 20 + i % 50))
cursor.execute('COMMIT')

conn.close()

6. Redis 优化

6.1 数据结构选择

选择合适的数据结构可以显著提升性能:

python
import redis

r = redis.Redis(host='localhost', port=6379, db=0)

# String:简单的键值对
r.set('user:1000:name', 'Alice')

# Hash:存储对象
r.hset('user:1000', mapping={
    'name': 'Alice',
    'age': 25,
    'email': 'alice@example.com'
})

# List:队列、栈
r.lpush('queue:tasks', 'task1', 'task2', 'task3')

# Set:去重、集合运算
r.sadd('tags:python', 'web', 'backend', 'async')

# Sorted Set:排行榜
r.zadd('leaderboard', {'player1': 100, 'player2': 200})

6.2 缓存策略

缓存穿透解决方案

python
import redis
import json

r = redis.Redis()

def get_user(user_id):
    # 1. 查询缓存
    cache_key = f'user:{user_id}'
    cached = r.get(cache_key)
    if cached:
        if cached == b'null':  # 防止缓存穿透
            return None
        return json.loads(cached)
    
    # 2. 查询数据库
    user = db.query_user(user_id)
    
    # 3. 更新缓存
    if user:
        r.setex(cache_key, 3600, json.dumps(user))
    else:
        r.setex(cache_key, 60, 'null')  # 缓存空结果
    
    return user

7. 相关资源