大表查询的优化方案
-
单表优化:
- 字段选择:尽量使用
TINYINT
、SMALLINT
、MEDIUMINT
作为整数类型,而非INT
;如果字段值非负,可以使用UNSIGNED
。对于字符串字段,使用枚举或整数代替字符串类型,使用TIMESTAMP
而非DATETIME
。尽量减少字段数量,建议在20个以内,避免使用NULL
字段,因为它们会增加查询复杂度并占用额外索引空间。 - 索引优化:索引不是越多越好,应根据查询需求有针对性地创建。避免在
WHERE
和ORDER BY
命令中涉及的列建立索引,避免对字段进行NULL
值判断,因为这会导致全表扫描。对于值分布稀疏的字段,如“性别”,不适合建索引。字符字段最好建前缀索引,避免使用主键和外键,尽量使用多列索引,并删除不必要的单列索引。 - 查询优化:开启慢查询日志来找出执行时间较长的SQL语句。避免列运算和复杂的查询操作,如使用
OR
而非IN
(建议IN
的个数控制在200以内)。避免使用函数和触发器,尽量使用同类型进行比较,避免在WHERE
子句中使用!=
或<>
操作符,因为这会导致索引失效。
- 字段选择:尽量使用
-
读写分离:
- 在高并发场景下,配置MySQL的主从复制,主库处理写操作,从库处理读操作。在应用层配置负载均衡器,将读请求分发到多个从库上,以提升读性能。确保主从数据同步的及时性和一致性。
-
分库分表:
- 当单表数据量过大时,考虑分库分表。垂直拆分是将表按业务模块或功能拆分到不同的数据库中;水平拆分是将同一个表的数据按照一定规则(如ID范围、哈希值)拆分到多个表中,每个表存储部分数据。
-
其他优化措施:
- 限定查询范围:使用
WHERE
子句限定查询范围,如时间范围、ID范围等。确保查询条件中的字段被索引覆盖,减少扫描的数据量。 - 使用合适的存储引擎:如
MyISAM
适合读密集型操作,而InnoDB
适合写密集型操作。根据具体需求选择合适的存储引擎。
- 限定查询范围:使用
- 慢查询日志,就是查询花费大量时间的日志,是指mysql记录所有执行超过long_query_time参数设定的时间阈值的SQL语句的日志,以帮助开发者分析和优化数据库查询性能。默认情况下,慢查询日志是关闭的,要使用慢查询日志功能,首先要开启慢查询日志功能。
-
如何定位慢SQL?
执行 SHOW PROFILE 命令时,它会显示关于服务器线程执行的详细信息,包括每个线程所执行的每个语句的执行时间、I/O 操作、上下文切换等。注意:通常在开发和问题诊断期间使用,而不是在生产环境中持续启用。
性能开销:SHOW PROFILE功能在启用时会对服务器的性能产生额外负担。每当一个查询执行时,MySQL服务器会收集详细的性能信息,包括CPU时间、等待时间、上下文切换次数等。这些信息的收集和存储会消耗额外的CPU和内存资源,这在高并发的生产环境中可能是不可接受的。
-- 启用性能监控
mysql> set profiling=1;
-- 执行SQL
mysql> SELECT * from member-- 性能分析
mysql> show profiles;