/** * 数据库查询优化器 * @file query-optimizer.js * @description 监控和优化SQL查询性能 */ const { sequelize } = require('./database-pool'); const { QueryTypes } = require('sequelize'); /** * 记录查询性能 * @param {string} query SQL查询语句 * @param {number} executionTime 执行时间(毫秒) * @returns {Promise} */ async function logQueryPerformance(query, executionTime) { try { // 简化查询语句(移除参数值) const simplifiedQuery = query.replace(/('([^']*)'|"([^"]*)"|`([^`]*)`)/g, '?'); // 记录到性能日志表 await sequelize.query( 'INSERT INTO query_performance_logs (query, execution_time, timestamp) VALUES (?, ?, NOW())', { replacements: [simplifiedQuery, executionTime], type: QueryTypes.INSERT } ).catch(() => { // 如果表不存在,创建表 return sequelize.query( `CREATE TABLE IF NOT EXISTS query_performance_logs ( id INT AUTO_INCREMENT PRIMARY KEY, query TEXT NOT NULL, execution_time FLOAT NOT NULL, timestamp DATETIME NOT NULL, INDEX (timestamp), INDEX (execution_time) )`, { type: QueryTypes.RAW } ).then(() => { // 重新尝试插入 return sequelize.query( 'INSERT INTO query_performance_logs (query, execution_time, timestamp) VALUES (?, ?, NOW())', { replacements: [simplifiedQuery, executionTime], type: QueryTypes.INSERT } ); }); }); } catch (error) { console.error('记录查询性能失败:', error); } } /** * 识别慢查询 * @param {number} threshold 慢查询阈值(毫秒),默认为500ms * @returns {Promise} 慢查询列表 */ async function identifySlowQueries(threshold = 500) { try { // 查询性能日志表中的慢查询 const slowQueries = await sequelize.query( 'SELECT query, AVG(execution_time) as avg_time, COUNT(*) as count, MAX(timestamp) as last_seen ' + 'FROM query_performance_logs ' + 'WHERE execution_time > ? ' + 'GROUP BY query ' + 'ORDER BY avg_time DESC', { replacements: [threshold], type: QueryTypes.SELECT } ).catch(() => { // 如果表不存在,返回空数组 return []; }); return slowQueries; } catch (error) { console.error('识别慢查询失败:', error); return []; } } /** * 分析和优化表 * @param {string} tableName 表名 * @returns {Promise} 优化结果 */ async function analyzeAndOptimizeTable(tableName) { try { // 分析表 await sequelize.query(`ANALYZE TABLE ${tableName}`, { type: QueryTypes.RAW }); // 优化表 const optimizeResult = await sequelize.query(`OPTIMIZE TABLE ${tableName}`, { type: QueryTypes.RAW }); return optimizeResult[0]; } catch (error) { console.error(`分析和优化表 ${tableName} 失败:`, error); return { error: error.message }; } } /** * 获取表的索引信息 * @param {string} tableName 表名 * @returns {Promise} 索引信息 */ async function getIndexInfo(tableName) { try { const indexInfo = await sequelize.query( 'SHOW INDEX FROM ??', { replacements: [tableName], type: QueryTypes.SELECT } ); return indexInfo; } catch (error) { console.error(`获取表 ${tableName} 的索引信息失败:`, error); return []; } } /** * 获取表信息 * @param {string} tableName 表名 * @returns {Promise} 表信息 */ async function getTableInfo(tableName) { try { // 获取表状态 const tableStatus = await sequelize.query( 'SHOW TABLE STATUS LIKE ?', { replacements: [tableName], type: QueryTypes.SELECT } ); // 获取表结构 const tableStructure = await sequelize.query( 'DESCRIBE ??', { replacements: [tableName], type: QueryTypes.SELECT } ); return { status: tableStatus[0] || {}, structure: tableStructure }; } catch (error) { console.error(`获取表 ${tableName} 信息失败:`, error); return { error: error.message }; } } /** * 解释查询计划 * @param {Object} query Sequelize查询对象 * @returns {Promise} 查询计划 */ async function explainQuery(query) { try { // 获取SQL语句 const sql = query.getQueryString(); // 执行EXPLAIN const explainResult = await sequelize.query( `EXPLAIN ${sql}`, { type: QueryTypes.SELECT } ); return explainResult; } catch (error) { console.error('解释查询计划失败:', error); return []; } } /** * 获取数据库状态 * @returns {Promise} 数据库状态 */ async function getDatabaseStatus() { try { // 获取全局状态 const globalStatus = await sequelize.query( 'SHOW GLOBAL STATUS', { type: QueryTypes.SELECT } ); // 转换为对象格式 const status = {}; globalStatus.forEach(item => { if (item.Variable_name && item.Value) { status[item.Variable_name] = item.Value; } }); // 提取关键指标 return { connections: { max_used: status.Max_used_connections, current: status.Threads_connected, running: status.Threads_running, created: status.Threads_created, cached: status.Threads_cached }, queries: { total: status.Questions, slow: status.Slow_queries, qps: status.Queries }, buffer_pool: { size: status.Innodb_buffer_pool_pages_total, free: status.Innodb_buffer_pool_pages_free, dirty: status.Innodb_buffer_pool_pages_dirty, reads: status.Innodb_buffer_pool_reads, read_requests: status.Innodb_buffer_pool_read_requests, hit_rate: status.Innodb_buffer_pool_read_requests && status.Innodb_buffer_pool_reads ? (1 - parseInt(status.Innodb_buffer_pool_reads) / parseInt(status.Innodb_buffer_pool_read_requests)) * 100 : 0 } }; } catch (error) { console.error('获取数据库状态失败:', error); return { error: error.message }; } } module.exports = { logQueryPerformance, identifySlowQueries, analyzeAndOptimizeTable, getIndexInfo, getTableInfo, explainQuery, getDatabaseStatus };