Ubuntu Java日志中SQL语句优化指南
在Ubuntu环境中,首先需要通过慢查询日志定位执行效率低的SQL语句。对于MySQL数据库,可通过以下命令开启慢查询日志:
-- 临时开启慢查询日志(重启后失效)
SET GLOBAL slow_query_log = 'ON';
-- 设置慢查询时间阈值(单位:秒,如1秒)
SET GLOBAL long_query_time = 1;
-- 查看慢查询日志文件路径
SHOW VARIABLES LIKE 'slow_query_log_file';
对于Java应用,也可通过框架(如Spring Boot)的配置自动记录慢SQL,例如在application.properties中添加:
spring.datasource.druid.filter.slowsql.slow-sql-millis=1000
spring.datasource.druid.filter.slowsql.log-slow-sql=true
这会将执行时间超过1秒的SQL记录到日志中,便于后续分析。
获取慢SQL后,使用EXPLAIN命令分析其执行计划,重点关注以下字段:
const(单条记录,如主键查询)、eq_ref(唯一索引关联)、ref(非唯一索引扫描)、range(范围扫描,如<、between)、index(索引全扫描)、ALL(全表扫描,需优先优化)。Using filesort(需额外排序)、Using temporary(使用临时表,性能极差)、Using index(覆盖索引,无需回表)需重点关注。例如,若type为ALL且rows很大,说明存在全表扫描,需优化索引。
user_id、order_status)。(shop_id, order_no),查询条件需包含shop_id才能命中索引)。mobile字段为VARCHAR类型,查询时使用mobile=12345678901会导致索引失效,应改为mobile='12345678901')。SUBSTR(phone, 1, 3) = '138',应改为phone >= '13800000000' AND phone < '13900000000')。OR连接非索引列(如name = 'iPhone' OR category_id = 10,应将category_id加上索引并改用UNION)。IN查询的范围(如IN列表过长,可改为JOIN或分批次查询)。SELECT *,只查询必要的字段(如SELECT id, name, price FROM product)。LIMIT限制结果集大小(如分页查询LIMIT 0, 10)。EXISTS代替IN(当子查询结果集较大时,EXISTS效率更高,如SELECT num FROM a WHERE EXISTS (SELECT 1 FROM b WHERE num = a.num))。SELECT *与JOIN组合(只查询需要的字段,减少回表操作)。LIMIT 10000, 10),使用延迟关联(先查询ID再关联,减少回表次数):SELECT t1.* FROM product t1
JOIN (SELECT id FROM product WHERE category_id = 1 ORDER BY create_time DESC LIMIT 10000, 10) t2
ON t1.id = t2.id;
INSERT INTO table VALUES (?, ?), (?, ?))代替循环单条插入,减少数据库交互次数。innodb_buffer_pool_size(InnoDB缓冲池大小,建议设置为物理内存的50%-70%,用于缓存数据和索引)。tmp_table_size和max_heap_table_size(内存临时表大小,避免大查询使用磁盘临时表)。INT代替VARCHAR存储数字,用VARCHAR(255)代替CHAR(255)节省空间)。