MySQL作为最流行的关系型数据库之一,其查询性能直接影响着应用系统的响应速度。本文将全面介绍MySQL中的高效检索方式,从索引优化到查询技巧,帮助开发者显著提升数据库查询效率。
B+树索引是MySQL最常用的索引类型:
-- 创建单列索引
CREATE INDEX idx_name ON users(name);
-- 创建复合索引(最左前缀原则)
CREATE INDEX idx_name_age ON users(name, age);
索引选择原则:
为WHERE、JOIN、ORDER BY子句中的列创建索引
区分度高的列优先建索引(如手机号比性别更适合)
避免过度索引,每个索引都会增加写操作开销
当索引包含查询需要的所有字段时,可以避免回表操作:
-- 使用覆盖索引
EXPLAIN SELECT user_id, username FROM users WHERE username LIKE '张%';
-- 对比需要回表的查询
EXPLAIN SELECT * FROM users WHERE username LIKE '张%';
典型全表扫描场景:
-- 未使用索引列查询
SELECT * FROM products WHERE price > 100;
-- 使用函数导致索引失效
SELECT * FROM users WHERE DATE(create_time) = '2023-01-01';
优化方案:
-- 为price添加索引
ALTER TABLE products ADD INDEX idx_price(price);
-- 改写日期查询
SELECT * FROM users
WHERE create_time BETWEEN '2023-01-01 00:00:00' AND '2023-01-01 23:59:59';
低效写法:
SELECT * FROM large_table LIMIT 1000000, 10;
优化方案:
-- 方案1:使用主键定位
-- 缺点:需要id连续,并且没有跳过,不适用
SELECT * FROM large_table
WHERE id > 1000000 ORDER BY id LIMIT 10;
-- 方案2:JOIN优化
SELECT t.* FROM large_table t
JOIN (SELECT id FROM large_table ORDER BY id LIMIT 1000000, 10) tmp
ON t.id = tmp.id;
-- 方案3:子查询
select * from tb_sku as s,
(select id from tb_sku order by id limit 9000000, 10) as a
where s.id = a.id;
可以让前端将上一次最后的id传过来,后续只需要 `id > x limit 10`
底层运用到倒排索引
对于文本内容的检索,全文索引比LIKE更高效:
-- 创建全文索引
ALTER TABLE articles ADD FULLTEXT INDEX ft_idx_content(content);
-- 使用全文检索
SELECT * FROM articles
WHERE MATCH(content) AGAINST('数据库优化' IN NATURAL LANGUAGE MODE);
备注:详情可了解 { 窗口函数 }
对海量数据表进行分区,提升查询效率:
-- 按范围分区
CREATE TABLE logs (
id INT AUTO_INCREMENT,
log_date DATE,
content TEXT,
PRIMARY KEY (id, log_date)
PARTITION BY RANGE (YEAR(log_date)) (
PARTITION p2020 VALUES LESS THAN (2021),
PARTITION p2021 VALUES LESS THAN (2022),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
-- 查询时自动选择分区
SELECT * FROM logs WHERE log_date BETWEEN '2021-01-01' AND '2021-12-31';
启用查询缓存(MySQL 8.0已移除该功能):
# my.cnf配置
query_cache_type = 1
query_cache_size = 64M
适用场景:
读多写少的应用
数据更新频率低的表
通过主从复制实现读写分离:
主库处理写操作
从库处理读操作
使用中间件(如MyCat、ShardingSphere)自动路由
启用慢查询日志:
# my.cnf配置
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 1
使用EXPLAIN分析:
EXPLAIN SELECT * FROM orders WHERE user_id = 100 AND status = 'paid';
分析关键指标:
type:最好达到ref或range级别
key:实际使用的索引
rows:预估扫描行数
对频繁更新的表进行定期优化:
-- 重建表,优化存储空间
OPTIMIZE TABLE frequently_updated_table;
-- 更新索引统计信息
ANALYZE TABLE large_table;
原始查询(执行时间2.1s):
SELECT * FROM products
WHERE category_id = 5
AND price BETWEEN 100 AND 500
AND stock > 0
ORDER BY sales DESC
LIMIT 20;
优化步骤:
备注:此处需要注意最左前缀匹配原则(即不能跳过某个字段)
创建复合索引:
ALTER TABLE products ADD INDEX
idx_category_price_stock_sales(category_id, price, stock, sales);
改写查询:
SELECT p.* FROM products p
JOIN (
SELECT id FROM products
WHERE category_id = 5
AND price BETWEEN 100 AND 500
AND stock > 0
ORDER BY sales DESC
LIMIT 20
) tmp ON p.id = tmp.id;
优化结果:执行时间降至0.05s
优化方式 | 适用场景 | 提升效果 | 实施难度 |
---|---|---|---|
单列索引 | 等值查询、排序字段 | ★★★☆ | ★★ |
复合索引 | 多条件组合查询 | ★★★★ | ★★★ |
覆盖索引 | 只查询索引列 | ★★★★☆ | ★★ |
全文索引 | 文本内容搜索 | ★★★☆ | ★★★ |
分区表 | 海量数据按条件筛选 | ★★★★ | ★★★★ |
查询重写 | 复杂分页、子查询 | ★★★☆ | ★★★★ |
通过合理组合这些优化策略,可以使MySQL的检索性能得到显著提升。建议在实际应用中通过EXPLAIN分析和慢查询日志持续监控查询性能,针对性地进行优化调整。