大数据量下的索引优化策略
大数据量下的索引优化策略
面试指北 · 通用
大数据量查询特点分析
1. 性能瓶颈识别
-- 查询执行时间分析
-- MySQL
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST
WHERE COMMAND = 'Query' AND TIME > 10;
-- PostgreSQL
SELECT query, state, query_start, now() - query_start as duration
FROM pg_stat_activity
WHERE state = 'active' AND now() - query_start > interval '10 seconds';
2. 数据分布特征
- 时序数据:按时间分区,时间维度索引
- 用户数据:按用户ID分片,用户维度索引
- 地理数据:空间索引优化
- 日志数据:压缩存储 + 稀疏索引
核心索引策略
1. 分区表 + 局部索引
-- PostgreSQL 分区示例
CREATE TABLE orders (
id BIGSERIAL,
user_id BIGINT,
created_at TIMESTAMP,
amount DECIMAL,
status VARCHAR(20)
) PARTITION BY RANGE (created_at);
-- 创建月度分区
CREATE TABLE orders_202401 PARTITION OF orders
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
-- 每个分区建立局部索引
CREATE INDEX idx_orders_202401_user ON orders_202401(user_id, status);
CREATE INDEX idx_orders_202401_amount ON orders_202401(amount) WHERE amount > 1000;
2. 复合索引优化
-- 基于查询频率设计复合索引
-- 高频查询:按用户查订单
CREATE INDEX idx_orders_user_time ON orders(user_id, created_at DESC, status);
-- 中频查询:按状态查询
CREATE INDEX idx_orders_status_time ON orders(status, created_at DESC)
WHERE status IN ('pending', 'processing');
-- 低频查询:按金额范围
CREATE INDEX idx_orders_amount ON orders(amount) WHERE amount > 10000;
3. 部分索引(PostgreSQL)
-- 只为活跃数据建索引,减少索引大小
CREATE INDEX idx_active_users ON users(last_login_at, user_id)
WHERE last_login_at > now() - interval '90 days';
-- 大表中的热点数据索引
CREATE INDEX idx_hot_products ON products(category_id, price)
WHERE status = 'active' AND stock_quantity > 0;
大表索引建立技巧
1. 在线索引创建
-- MySQL 8.0+
ALTER TABLE large_table ADD INDEX idx_name(column) ALGORITHM=INPLACE, LOCK=NONE;
-- PostgreSQL
CREATE INDEX CONCURRENTLY idx_name ON large_table(column);
2. 批量索引创建
-- 关闭自动提交,批量创建
SET autocommit = 0;
CREATE INDEX idx1 ON table(col1);
CREATE INDEX idx2 ON table(col2);
CREATE INDEX idx3 ON table(col3);
COMMIT;
3. 分段创建策略
-- 大表分段创建索引,避免锁表时间过长
-- 步骤1:创建部分索引
CREATE INDEX idx_temp ON large_table(column) WHERE id BETWEEN 1 AND 1000000;
-- 步骤2:扩展索引范围
DROP INDEX idx_temp;
CREATE INDEX idx_final ON large_table(column);
特定场景优化
1. 时序数据优化
-- BRIN索引适合大表时序数据
CREATE INDEX idx_logs_time_brin ON access_logs USING BRIN(created_at);
-- 复合BRIN索引
CREATE INDEX idx_logs_multi_brin ON access_logs USING BRIN(created_at, user_id);
-- 查询示例
SELECT * FROM access_logs
WHERE created_at BETWEEN '2024-01-01' AND '2024-01-31'
AND user_id = 12345;
2. JSON数据优化
-- PostgreSQL GIN索引
CREATE INDEX idx_metadata_gin ON products USING GIN(metadata);
-- 函数索引提取特定JSON字段
CREATE INDEX idx_product_category ON products((metadata->>'category'));
-- 查询优化
SELECT * FROM products
WHERE metadata->>'category' = 'electronics'
AND (metadata->>'price')::numeric > 1000;
3. 全文搜索优化
-- PostgreSQL 全文搜索
CREATE INDEX idx_content_fts ON articles USING GIN(to_tsvector('english', content));
-- 多语言支持
CREATE INDEX idx_content_zh ON articles USING GIN(to_tsvector('zhparser', content));
-- 查询示例
SELECT * FROM articles
WHERE to_tsvector('english', content) @@ plainto_tsquery('database optimization');
索引监控与调优
1. 索引使用情况监控
-- MySQL 索引使用统计
SELECT
s.TABLE_NAME,
s.INDEX_NAME,
s.CARDINALITY,
i.STAT_VALUE as pages_used
FROM INFORMATION_SCHEMA.STATISTICS s
LEFT JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS i
ON s.TABLE_NAME = i.NAME
WHERE s.TABLE_SCHEMA = 'your_database'
ORDER BY s.CARDINALITY DESC;
-- PostgreSQL 索引效率分析
SELECT
schemaname,
tablename,
indexname,
idx_scan,
idx_tup_read,
idx_tup_fetch,
pg_size_pretty(pg_relation_size(indexrelid)) as size
FROM pg_stat_user_indexes
ORDER BY idx_scan DESC;
2. 慢查询索引优化
-- 找出缺失索引的慢查询
-- MySQL
SELECT
DIGEST_TEXT,
COUNT_STAR,
AVG_TIMER_WAIT/1000000000 as avg_time_sec,
SUM_ROWS_EXAMINED/COUNT_STAR as avg_rows_examined
FROM performance_schema.events_statements_summary_by_digest
WHERE AVG_TIMER_WAIT > 1000000000 -- 超过1秒的查询
ORDER BY AVG_TIMER_WAIT DESC;
3. 索引碎片整理
-- MySQL
OPTIMIZE TABLE large_table;
-- PostgreSQL
REINDEX INDEX CONCURRENTLY idx_name;
-- 定期维护脚本
ANALYZE TABLE large_table;
高级优化技巧
1. 列存储索引(适用场景)
-- MySQL 8.0 列存储引擎
CREATE TABLE analytics_data (
date_col DATE,
user_id BIGINT,
metric_value DECIMAL,
INDEX idx_date(date_col),
INDEX idx_user(user_id)
) ENGINE=COLUMNSTORE;
2. 内存表缓存热点数据
-- 热点数据内存表
CREATE TABLE hot_cache (
id BIGINT PRIMARY KEY,
data JSON,
last_updated TIMESTAMP
) ENGINE=MEMORY;
-- 定期同步策略
INSERT INTO hot_cache
SELECT id, data, updated_at
FROM large_table
WHERE updated_at > DATE_SUB(NOW(), INTERVAL 1 HOUR);
3. 读写分离索引策略
-- 主库:写优化,少索引
CREATE INDEX idx_write_only ON table(id, status);
-- 从库:读优化,多索引
CREATE INDEX idx_read_user ON table(user_id, created_at);
CREATE INDEX idx_read_category ON table(category, price);
CREATE INDEX idx_read_search ON table(title, description);
性能测试验证
1. 索引效果对比
-- 测试前后性能对比
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM large_table
WHERE complex_condition;
-- 关注指标:
-- - Execution time
-- - Buffers hit/read
-- - Rows examined vs returned
2. 并发性能测试
# 使用工具测试并发查询性能
# sysbench, pgbench, 或自定义脚本
sysbench oltp_read_write \
--table-size=10000000 \
--mysql-db=testdb \
--threads=64 \
--time=300 \
run
合理的大数据量索引设计需要结合具体业务场景,通过监控数据驱动优化决策,定期评估和调整索引策略。
License:
CC BY 4.0