在这里插入图片描述

目录

  1. 概述
  2. 数据库查询优化基础
  3. 核心优化策略
  4. Kotlin 源代码
  5. JavaScript 编译代码
  6. ArkTS 调用代码
  7. 优化指标详解
  8. 实战案例

概述

在现代应用开发中,数据库查询的性能直接影响整个系统的响应速度和用户体验。数据库查询优化是提升系统性能的重要手段,它通过分析查询执行计划、识别性能瓶颈、提供优化建议来帮助开发者写出高效的SQL语句。本文档介绍如何在 Kotlin Multiplatform (KMP) 框架下,结合 OpenHarmony 鸿蒙操作系统,实现一个功能完整的数据库查询优化工具。

数据库查询优化工具是一个综合性的性能分析平台,它不仅能够分析SQL查询的执行效率,还能够识别常见的性能问题、提供具体的优化建议、生成详细的优化报告。通过KMP框架的跨端能力,这个工具可以在Android、iOS、Web和OpenHarmony等多个平台上运行,为开发者提供了一个强大的数据库性能分析和优化工具。

数据库查询优化的重要性

数据库查询优化在现代应用开发中的重要性日益凸显:

  1. 性能提升:优化查询可以显著提升数据库响应速度,减少用户等待时间。
  2. 资源节省:高效的查询可以减少数据库的CPU、内存和磁盘IO消耗。
  3. 并发能力:优化查询可以提升数据库的并发处理能力,支持更多用户。
  4. 成本降低:通过优化查询,可以减少数据库服务器的需求,降低运营成本。
  5. 系统稳定:避免低效查询导致的数据库阻塞和系统崩溃。

工具的核心价值

数据库查询优化工具提供以下价值:

  • 查询分析:分析SQL查询的执行计划和性能指标
  • 问题识别:自动识别常见的性能问题,如缺少索引、全表扫描等
  • 优化建议:根据分析结果提供具体的优化建议
  • 性能对比:支持优化前后的性能对比,量化优化效果
  • 索引建议:根据查询模式建议创建合适的索引
  • 跨平台支持:一份代码可在多个平台运行,提高开发效率

数据库查询优化基础

查询性能指标

执行时间(Execution Time):查询从开始到完成所需的时间,包括解析、优化、执行等阶段。执行时间是最直观的性能指标。

扫描行数(Rows Scanned):查询需要扫描的数据行数。扫描行数越少,性能越好。

返回行数(Rows Returned):查询返回的结果行数。通常应该远小于扫描行数。

索引使用情况(Index Usage):查询是否使用了索引。使用索引的查询通常性能更好。

查询成本(Query Cost):数据库估计的查询成本,通常用相对值表示。

常见的性能问题

全表扫描:查询没有使用索引,需要扫描整个表。这是最常见的性能问题。

缺少索引:表上没有创建合适的索引,导致查询性能低下。

索引失效:虽然创建了索引,但由于查询条件的写法不当,导致索引未被使用。

JOIN操作不当:多表JOIN时没有使用合适的连接条件或顺序,导致性能低下。

子查询低效:子查询返回大量数据或执行多次,导致整体性能低下。

排序操作:没有使用索引的排序操作需要在内存中进行,消耗大量资源。

优化方法论

索引优化:创建合适的索引,包括单列索引、复合索引等。

查询改写:改写查询语句,使其更高效,如避免函数调用、使用JOIN替代子查询等。

执行计划优化:通过HINT或其他方式指导数据库选择更优的执行计划。

数据库参数调优:调整数据库参数,如缓冲区大小、并发数等。


核心优化策略

1. 索引优化

创建合适的索引是提升查询性能的最有效方法。单列索引适合于单条件查询,复合索引适合于多条件查询。

2. 查询改写

通过改写查询语句,可以避免低效的操作。例如,使用JOIN替代子查询、避免在WHERE条件中使用函数等。

3. 分页优化

对于大结果集,应该使用分页查询而不是一次性加载所有数据。

4. 缓存策略

对于频繁查询的数据,可以使用缓存来避免重复查询数据库。

5. 数据库连接池

使用连接池可以减少连接创建的开销,提升并发性能。

6. 查询结果缓存

对于不经常变化的查询结果,可以进行缓存,避免重复查询。


Kotlin 源代码

// DatabaseQueryOptimizer.kt
import java.time.LocalDateTime
import kotlin.math.*

data class QueryAnalysis(
    val id: String,
    val querySQL: String,
    val executionTime: Long,
    val rowsScanned: Long,
    val rowsReturned: Long,
    val indexUsed: Boolean,
    val queryCost: Double,
    val timestamp: String,
    val executionPlan: String = ""
)

data class OptimizationSuggestion(
    val id: String,
    val queryId: String,
    val suggestionType: String,
    val priority: String,
    val description: String,
    val expectedImprovement: Double,
    val implementationSteps: List<String>,
    val timestamp: String
)

data class IndexRecommendation(
    val id: String,
    val tableName: String,
    val columns: List<String>,
    val indexType: String,
    val estimatedSize: Long,
    val estimatedPerformanceGain: Double,
    val priority: String,
    val reason: String
)

data class QueryPerformanceMetrics(
    val totalQueries: Long,
    val averageExecutionTime: Double,
    val slowestQuery: QueryAnalysis?,
    val fastestQuery: QueryAnalysis?,
    val averageRowsScanned: Double,
    val indexUsageRate: Double,
    val totalOptimizationSuggestions: Long,
    val implementedSuggestions: Long
)

class DatabaseQueryOptimizer {
    private val queryAnalyses = mutableListOf<QueryAnalysis>()
    private val suggestions = mutableListOf<OptimizationSuggestion>()
    private val indexRecommendations = mutableListOf<IndexRecommendation>()
    private var queryIdCounter = 0
    private var suggestionIdCounter = 0
    private var indexIdCounter = 0
    
    // 分析查询
    fun analyzeQuery(
        querySQL: String,
        executionTime: Long,
        rowsScanned: Long,
        rowsReturned: Long,
        indexUsed: Boolean,
        executionPlan: String = ""
    ): QueryAnalysis {
        val id = "QUERY${++queryIdCounter}"
        
        // 计算查询成本
        val queryCost = calculateQueryCost(rowsScanned, executionTime, indexUsed)
        
        val analysis = QueryAnalysis(
            id = id,
            querySQL = querySQL,
            executionTime = executionTime,
            rowsScanned = rowsScanned,
            rowsReturned = rowsReturned,
            indexUsed = indexUsed,
            queryCost = queryCost,
            timestamp = LocalDateTime.now().toString(),
            executionPlan = executionPlan
        )
        
        queryAnalyses.add(analysis)
        
        // 自动生成优化建议
        generateOptimizationSuggestions(analysis)
        
        return analysis
    }
    
    // 生成优化建议
    private fun generateOptimizationSuggestions(analysis: QueryAnalysis) {
        val suggestions = mutableListOf<OptimizationSuggestion>()
        
        // 检查全表扫描
        if (!analysis.indexUsed && analysis.rowsScanned > 10000) {
            suggestions.add(OptimizationSuggestion(
                id = "SUGG${++suggestionIdCounter}",
                queryId = analysis.id,
                suggestionType = "ADD_INDEX",
                priority = "HIGH",
                description = "查询未使用索引,建议创建合适的索引以加速查询",
                expectedImprovement = 50.0,
                implementationSteps = listOf(
                    "分析查询的WHERE条件",
                    "识别高频查询的过滤列",
                    "创建单列或复合索引",
                    "验证索引是否被使用"
                ),
                timestamp = LocalDateTime.now().toString()
            ))
        }
        
        // 检查扫描行数与返回行数的比例
        if (analysis.rowsScanned > 0) {
            val ratio = analysis.rowsReturned.toDouble() / analysis.rowsScanned
            if (ratio < 0.1) {
                suggestions.add(OptimizationSuggestion(
                    id = "SUGG${++suggestionIdCounter}",
                    queryId = analysis.id,
                    suggestionType = "IMPROVE_WHERE_CLAUSE",
                    priority = "MEDIUM",
                    description = "返回行数远小于扫描行数,建议优化WHERE条件以减少扫描范围",
                    expectedImprovement = 30.0,
                    implementationSteps = listOf(
                        "分析WHERE条件的选择性",
                        "考虑添加更多过滤条件",
                        "优化条件的组合方式",
                        "使用更具体的查询条件"
                    ),
                    timestamp = LocalDateTime.now().toString()
                ))
            }
        }
        
        // 检查执行时间
        if (analysis.executionTime > 1000) {
            suggestions.add(OptimizationSuggestion(
                id = "SUGG${++suggestionIdCounter}",
                queryId = analysis.id,
                suggestionType = "SLOW_QUERY",
                priority = "HIGH",
                description = "查询执行时间过长(${analysis.executionTime}ms),需要优化",
                expectedImprovement = 40.0,
                implementationSteps = listOf(
                    "检查是否有全表扫描",
                    "检查是否有多个JOIN操作",
                    "考虑使用缓存",
                    "考虑分页查询"
                ),
                timestamp = LocalDateTime.now().toString()
            ))
        }
        
        this.suggestions.addAll(suggestions)
    }
    
    // 推荐索引
    fun recommendIndexes(tableName: String, queryPatterns: List<String>): List<IndexRecommendation> {
        val recommendations = mutableListOf<IndexRecommendation>()
        
        // 分析查询模式,推荐索引
        for (pattern in queryPatterns) {
            val columns = extractColumnsFromPattern(pattern)
            
            if (columns.isNotEmpty()) {
                val recommendation = IndexRecommendation(
                    id = "IDX${++indexIdCounter}",
                    tableName = tableName,
                    columns = columns,
                    indexType = if (columns.size == 1) "SINGLE" else "COMPOSITE",
                    estimatedSize = calculateIndexSize(columns),
                    estimatedPerformanceGain = calculatePerformanceGain(columns),
                    priority = if (columns.size == 1) "HIGH" else "MEDIUM",
                    reason = "根据查询模式推荐的索引"
                )
                
                recommendations.add(recommendation)
            }
        }
        
        indexRecommendations.addAll(recommendations)
        return recommendations
    }
    
    // 获取查询性能指标
    fun getPerformanceMetrics(): QueryPerformanceMetrics {
        if (queryAnalyses.isEmpty()) {
            return QueryPerformanceMetrics(
                totalQueries = 0,
                averageExecutionTime = 0.0,
                slowestQuery = null,
                fastestQuery = null,
                averageRowsScanned = 0.0,
                indexUsageRate = 0.0,
                totalOptimizationSuggestions = 0,
                implementedSuggestions = 0
            )
        }
        
        val totalQueries = queryAnalyses.size.toLong()
        val averageExecutionTime = queryAnalyses.map { it.executionTime }.average()
        val slowestQuery = queryAnalyses.maxByOrNull { it.executionTime }
        val fastestQuery = queryAnalyses.minByOrNull { it.executionTime }
        val averageRowsScanned = queryAnalyses.map { it.rowsScanned }.average()
        val indexUsageRate = (queryAnalyses.count { it.indexUsed }.toDouble() / totalQueries) * 100
        val totalOptimizationSuggestions = suggestions.size.toLong()
        val implementedSuggestions = 0L // 实际应用中应该追踪实现状态
        
        return QueryPerformanceMetrics(
            totalQueries = totalQueries,
            averageExecutionTime = averageExecutionTime,
            slowestQuery = slowestQuery,
            fastestQuery = fastestQuery,
            averageRowsScanned = averageRowsScanned,
            indexUsageRate = indexUsageRate,
            totalOptimizationSuggestions = totalOptimizationSuggestions,
            implementedSuggestions = implementedSuggestions
        )
    }
    
    // 获取优化建议
    fun getOptimizationSuggestions(priority: String = ""): List<OptimizationSuggestion> {
        return if (priority.isEmpty()) {
            suggestions.toList()
        } else {
            suggestions.filter { it.priority == priority }
        }
    }
    
    // 获取索引推荐
    fun getIndexRecommendations(): List<IndexRecommendation> {
        return indexRecommendations.toList()
    }
    
    // 计算查询成本
    private fun calculateQueryCost(rowsScanned: Long, executionTime: Long, indexUsed: Boolean): Double {
        var cost = rowsScanned.toDouble() * 0.1
        cost += executionTime.toDouble() * 0.5
        if (!indexUsed) cost *= 2.0
        return cost
    }
    
    // 从查询模式中提取列名
    private fun extractColumnsFromPattern(pattern: String): List<String> {
        val columns = mutableListOf<String>()
        
        // 简单的列名提取逻辑
        val whereRegex = Regex("WHERE\\s+([\\w,\\s=<>]+)", RegexOption.IGNORE_CASE)
        val match = whereRegex.find(pattern)
        
        if (match != null) {
            val conditions = match.groupValues[1].split(",")
            for (condition in conditions) {
                val columnName = condition.split("=", "<", ">")[0].trim()
                if (columnName.isNotEmpty()) {
                    columns.add(columnName)
                }
            }
        }
        
        return columns
    }
    
    // 计算索引大小
    private fun calculateIndexSize(columns: List<String>): Long {
        // 估计索引大小,每列约100KB
        return (columns.size * 100 * 1024).toLong()
    }
    
    // 计算性能提升
    private fun calculatePerformanceGain(columns: List<String>): Double {
        // 单列索引通常提升30-50%,复合索引提升50-80%
        return if (columns.size == 1) 40.0 else 60.0
    }
    
    // 生成优化报告
    fun generateOptimizationReport(): Map<String, Any> {
        val metrics = getPerformanceMetrics()
        val highPrioritySuggestions = getOptimizationSuggestions("HIGH")
        val indexRecs = getIndexRecommendations()
        
        return mapOf(
            "timestamp" to LocalDateTime.now().toString(),
            "metrics" to metrics,
            "highPrioritySuggestions" to highPrioritySuggestions,
            "indexRecommendations" to indexRecs,
            "summary" to generateSummary(metrics, highPrioritySuggestions),
            "nextSteps" to generateNextSteps(highPrioritySuggestions)
        )
    }
    
    // 生成摘要
    private fun generateSummary(metrics: QueryPerformanceMetrics, suggestions: List<OptimizationSuggestion>): String {
        val sb = StringBuilder()
        sb.append("数据库查询优化分析摘要:\n")
        sb.append("总查询数: ${metrics.totalQueries}\n")
        sb.append("平均执行时间: ${String.format("%.2f", metrics.averageExecutionTime)}ms\n")
        sb.append("索引使用率: ${String.format("%.2f", metrics.indexUsageRate)}%\n")
        sb.append("高优先级建议: ${suggestions.size}条\n")
        
        if (metrics.slowestQuery != null) {
            sb.append("最慢查询执行时间: ${metrics.slowestQuery.executionTime}ms\n")
        }
        
        return sb.toString()
    }
    
    // 生成后续步骤
    private fun generateNextSteps(suggestions: List<OptimizationSuggestion>): List<String> {
        val steps = mutableListOf<String>()
        
        for (suggestion in suggestions.take(3)) {
            steps.add("${suggestion.suggestionType}: ${suggestion.description}")
        }
        
        if (suggestions.size > 3) {
            steps.add("还有${suggestions.size - 3}条建议,请查看完整报告")
        }
        
        return steps
    }
    
    // 清空数据
    fun clearData() {
        queryAnalyses.clear()
        suggestions.clear()
        indexRecommendations.clear()
    }
}

fun main() {
    val optimizer = DatabaseQueryOptimizer()
    
    // 模拟查询分析
    optimizer.analyzeQuery(
        querySQL = "SELECT * FROM users WHERE age > 18",
        executionTime = 150,
        rowsScanned = 50000,
        rowsReturned = 30000,
        indexUsed = false
    )
    
    optimizer.analyzeQuery(
        querySQL = "SELECT * FROM orders WHERE user_id = 123 AND status = 'completed'",
        executionTime = 2500,
        rowsScanned = 100000,
        rowsReturned = 50,
        indexUsed = false
    )
    
    // 推荐索引
    optimizer.recommendIndexes("orders", listOf(
        "SELECT * FROM orders WHERE user_id = ?",
        "SELECT * FROM orders WHERE status = ?",
        "SELECT * FROM orders WHERE user_id = ? AND status = ?"
    ))
    
    // 获取性能指标
    val metrics = optimizer.getPerformanceMetrics()
    println("数据库查询性能指标:")
    println("总查询数: ${metrics.totalQueries}")
    println("平均执行时间: ${String.format("%.2f", metrics.averageExecutionTime)}ms")
    println("索引使用率: ${String.format("%.2f", metrics.indexUsageRate)}%")
    
    // 获取优化建议
    val suggestions = optimizer.getOptimizationSuggestions("HIGH")
    println("\n高优先级优化建议: ${suggestions.size}条")
    
    // 生成报告
    val report = optimizer.generateOptimizationReport()
    println("\n优化报告: $report")
}

Kotlin代码说明:这个Kotlin实现提供了完整的数据库查询优化功能。DatabaseQueryOptimizer 类能够分析查询性能、自动生成优化建议、推荐索引、生成详细报告。通过数据类定义各种分析结果,代码结构清晰。系统支持多维度的性能分析,从单个查询的详细指标到整体的性能趋势,为开发者提供了全面的数据库优化能力。


JavaScript 编译代码

// DatabaseQueryOptimizer.js
class QueryAnalysis {
    constructor(id, querySQL, executionTime, rowsScanned, rowsReturned, indexUsed, queryCost, timestamp, executionPlan = "") {
        this.id = id;
        this.querySQL = querySQL;
        this.executionTime = executionTime;
        this.rowsScanned = rowsScanned;
        this.rowsReturned = rowsReturned;
        this.indexUsed = indexUsed;
        this.queryCost = queryCost;
        this.timestamp = timestamp;
        this.executionPlan = executionPlan;
    }
}

class OptimizationSuggestion {
    constructor(id, queryId, suggestionType, priority, description, expectedImprovement, implementationSteps, timestamp) {
        this.id = id;
        this.queryId = queryId;
        this.suggestionType = suggestionType;
        this.priority = priority;
        this.description = description;
        this.expectedImprovement = expectedImprovement;
        this.implementationSteps = implementationSteps;
        this.timestamp = timestamp;
    }
}

class IndexRecommendation {
    constructor(id, tableName, columns, indexType, estimatedSize, estimatedPerformanceGain, priority, reason) {
        this.id = id;
        this.tableName = tableName;
        this.columns = columns;
        this.indexType = indexType;
        this.estimatedSize = estimatedSize;
        this.estimatedPerformanceGain = estimatedPerformanceGain;
        this.priority = priority;
        this.reason = reason;
    }
}

class QueryPerformanceMetrics {
    constructor(totalQueries, averageExecutionTime, slowestQuery, fastestQuery, averageRowsScanned, indexUsageRate, totalOptimizationSuggestions, implementedSuggestions) {
        this.totalQueries = totalQueries;
        this.averageExecutionTime = averageExecutionTime;
        this.slowestQuery = slowestQuery;
        this.fastestQuery = fastestQuery;
        this.averageRowsScanned = averageRowsScanned;
        this.indexUsageRate = indexUsageRate;
        this.totalOptimizationSuggestions = totalOptimizationSuggestions;
        this.implementedSuggestions = implementedSuggestions;
    }
}

class DatabaseQueryOptimizer {
    constructor() {
        this.queryAnalyses = [];
        this.suggestions = [];
        this.indexRecommendations = [];
        this.queryIdCounter = 0;
        this.suggestionIdCounter = 0;
        this.indexIdCounter = 0;
    }
    
    analyzeQuery(querySQL, executionTime, rowsScanned, rowsReturned, indexUsed, executionPlan = "") {
        const id = `QUERY${++this.queryIdCounter}`;
        const queryCost = this.calculateQueryCost(rowsScanned, executionTime, indexUsed);
        
        const analysis = new QueryAnalysis(
            id,
            querySQL,
            executionTime,
            rowsScanned,
            rowsReturned,
            indexUsed,
            queryCost,
            new Date().toISOString(),
            executionPlan
        );
        
        this.queryAnalyses.push(analysis);
        this.generateOptimizationSuggestions(analysis);
        
        return analysis;
    }
    
    generateOptimizationSuggestions(analysis) {
        const suggestions = [];
        
        if (!analysis.indexUsed && analysis.rowsScanned > 10000) {
            suggestions.push(new OptimizationSuggestion(
                `SUGG${++this.suggestionIdCounter}`,
                analysis.id,
                "ADD_INDEX",
                "HIGH",
                "查询未使用索引,建议创建合适的索引以加速查询",
                50.0,
                [
                    "分析查询的WHERE条件",
                    "识别高频查询的过滤列",
                    "创建单列或复合索引",
                    "验证索引是否被使用"
                ],
                new Date().toISOString()
            ));
        }
        
        if (analysis.rowsScanned > 0) {
            const ratio = analysis.rowsReturned / analysis.rowsScanned;
            if (ratio < 0.1) {
                suggestions.push(new OptimizationSuggestion(
                    `SUGG${++this.suggestionIdCounter}`,
                    analysis.id,
                    "IMPROVE_WHERE_CLAUSE",
                    "MEDIUM",
                    "返回行数远小于扫描行数,建议优化WHERE条件以减少扫描范围",
                    30.0,
                    [
                        "分析WHERE条件的选择性",
                        "考虑添加更多过滤条件",
                        "优化条件的组合方式",
                        "使用更具体的查询条件"
                    ],
                    new Date().toISOString()
                ));
            }
        }
        
        if (analysis.executionTime > 1000) {
            suggestions.push(new OptimizationSuggestion(
                `SUGG${++this.suggestionIdCounter}`,
                analysis.id,
                "SLOW_QUERY",
                "HIGH",
                `查询执行时间过长(${analysis.executionTime}ms),需要优化`,
                40.0,
                [
                    "检查是否有全表扫描",
                    "检查是否有多个JOIN操作",
                    "考虑使用缓存",
                    "考虑分页查询"
                ],
                new Date().toISOString()
            ));
        }
        
        this.suggestions.push(...suggestions);
    }
    
    recommendIndexes(tableName, queryPatterns) {
        const recommendations = [];
        
        for (const pattern of queryPatterns) {
            const columns = this.extractColumnsFromPattern(pattern);
            
            if (columns.length > 0) {
                const recommendation = new IndexRecommendation(
                    `IDX${++this.indexIdCounter}`,
                    tableName,
                    columns,
                    columns.length === 1 ? "SINGLE" : "COMPOSITE",
                    this.calculateIndexSize(columns),
                    this.calculatePerformanceGain(columns),
                    columns.length === 1 ? "HIGH" : "MEDIUM",
                    "根据查询模式推荐的索引"
                );
                
                recommendations.push(recommendation);
            }
        }
        
        this.indexRecommendations.push(...recommendations);
        return recommendations;
    }
    
    getPerformanceMetrics() {
        if (this.queryAnalyses.length === 0) {
            return new QueryPerformanceMetrics(0, 0, null, null, 0, 0, 0, 0);
        }
        
        const totalQueries = this.queryAnalyses.length;
        const executionTimes = this.queryAnalyses.map(q => q.executionTime);
        const averageExecutionTime = executionTimes.reduce((a, b) => a + b, 0) / executionTimes.length;
        const slowestQuery = this.queryAnalyses.reduce((max, q) => q.executionTime > max.executionTime ? q : max);
        const fastestQuery = this.queryAnalyses.reduce((min, q) => q.executionTime < min.executionTime ? q : min);
        const averageRowsScanned = this.queryAnalyses.map(q => q.rowsScanned).reduce((a, b) => a + b, 0) / totalQueries;
        const indexUsageRate = (this.queryAnalyses.filter(q => q.indexUsed).length / totalQueries) * 100;
        
        return new QueryPerformanceMetrics(
            totalQueries,
            averageExecutionTime,
            slowestQuery,
            fastestQuery,
            averageRowsScanned,
            indexUsageRate,
            this.suggestions.length,
            0
        );
    }
    
    getOptimizationSuggestions(priority = "") {
        return priority ? this.suggestions.filter(s => s.priority === priority) : this.suggestions;
    }
    
    getIndexRecommendations() {
        return this.indexRecommendations;
    }
    
    calculateQueryCost(rowsScanned, executionTime, indexUsed) {
        let cost = rowsScanned * 0.1;
        cost += executionTime * 0.5;
        if (!indexUsed) cost *= 2.0;
        return cost;
    }
    
    extractColumnsFromPattern(pattern) {
        const columns = [];
        const whereRegex = /WHERE\s+([\w,\s=<>]+)/i;
        const match = pattern.match(whereRegex);
        
        if (match) {
            const conditions = match[1].split(",");
            for (const condition of conditions) {
                const columnName = condition.split(/[=<>]/)[0].trim();
                if (columnName) {
                    columns.push(columnName);
                }
            }
        }
        
        return columns;
    }
    
    calculateIndexSize(columns) {
        return columns.length * 100 * 1024;
    }
    
    calculatePerformanceGain(columns) {
        return columns.length === 1 ? 40.0 : 60.0;
    }
    
    generateOptimizationReport() {
        const metrics = this.getPerformanceMetrics();
        const highPrioritySuggestions = this.getOptimizationSuggestions("HIGH");
        const indexRecs = this.getIndexRecommendations();
        
        return {
            timestamp: new Date().toISOString(),
            metrics: metrics,
            highPrioritySuggestions: highPrioritySuggestions,
            indexRecommendations: indexRecs,
            summary: this.generateSummary(metrics, highPrioritySuggestions),
            nextSteps: this.generateNextSteps(highPrioritySuggestions)
        };
    }
    
    generateSummary(metrics, suggestions) {
        let summary = "数据库查询优化分析摘要:\n";
        summary += `总查询数: ${metrics.totalQueries}\n`;
        summary += `平均执行时间: ${metrics.averageExecutionTime.toFixed(2)}ms\n`;
        summary += `索引使用率: ${metrics.indexUsageRate.toFixed(2)}%\n`;
        summary += `高优先级建议: ${suggestions.length}条\n`;
        
        if (metrics.slowestQuery) {
            summary += `最慢查询执行时间: ${metrics.slowestQuery.executionTime}ms\n`;
        }
        
        return summary;
    }
    
    generateNextSteps(suggestions) {
        const steps = [];
        
        for (const suggestion of suggestions.slice(0, 3)) {
            steps.push(`${suggestion.suggestionType}: ${suggestion.description}`);
        }
        
        if (suggestions.length > 3) {
            steps.push(`还有${suggestions.length - 3}条建议,请查看完整报告`);
        }
        
        return steps;
    }
    
    clearData() {
        this.queryAnalyses = [];
        this.suggestions = [];
        this.indexRecommendations = [];
    }
}

// 使用示例
const optimizer = new DatabaseQueryOptimizer();

optimizer.analyzeQuery(
    "SELECT * FROM users WHERE age > 18",
    150,
    50000,
    30000,
    false
);

optimizer.analyzeQuery(
    "SELECT * FROM orders WHERE user_id = 123 AND status = 'completed'",
    2500,
    100000,
    50,
    false
);

optimizer.recommendIndexes("orders", [
    "SELECT * FROM orders WHERE user_id = ?",
    "SELECT * FROM orders WHERE status = ?",
    "SELECT * FROM orders WHERE user_id = ? AND status = ?"
]);

const metrics = optimizer.getPerformanceMetrics();
console.log("数据库查询性能指标:");
console.log("总查询数:", metrics.totalQueries);
console.log("平均执行时间:", metrics.averageExecutionTime.toFixed(2), "ms");
console.log("索引使用率:", metrics.indexUsageRate.toFixed(2), "%");

const suggestions = optimizer.getOptimizationSuggestions("HIGH");
console.log("\n高优先级优化建议:", suggestions.length, "条");

const report = optimizer.generateOptimizationReport();
console.log("\n优化报告:", report);

JavaScript代码说明:JavaScript版本是Kotlin代码的直接转译。我们使用ES6的class语法定义各个类,使用数组方法进行数据处理。整体逻辑和算法与Kotlin版本保持一致,确保跨平台的一致性。JavaScript的灵活性使得代码更加简洁,同时保持了清晰的结构和完整的功能。


ArkTS 调用代码

// DatabaseOptimizerPage.ets
import { DatabaseQueryOptimizer } from './DatabaseQueryOptimizer';

@Entry
@Component
struct DatabaseOptimizerPage {
    @State querySQL: string = '';
    @State executionTime: number = 150;
    @State rowsScanned: number = 50000;
    @State rowsReturned: number = 30000;
    @State indexUsed: boolean = false;
    @State selectedTab: number = 0;
    @State queryAnalyses: Array<any> = [];
    @State suggestions: Array<any> = [];
    @State indexRecommendations: Array<any> = [];
    @State metrics: any = null;
    @State report: any = null;
    @State isLoading: boolean = false;
    @State errorMessage: string = '';
    @State tableName: string = '';
    @State queryPatterns: Array<string> = [];
    
    private optimizer: DatabaseQueryOptimizer = new DatabaseQueryOptimizer();
    
    analyzeQuery() {
        if (!this.querySQL.trim()) {
            this.errorMessage = '请输入SQL查询语句';
            return;
        }
        
        this.isLoading = true;
        this.errorMessage = '';
        
        try {
            this.optimizer.analyzeQuery(
                this.querySQL,
                this.executionTime,
                this.rowsScanned,
                this.rowsReturned,
                this.indexUsed
            );
            
            this.queryAnalyses = this.optimizer.queryAnalyses;
            this.suggestions = this.optimizer.getOptimizationSuggestions();
            this.metrics = this.optimizer.getPerformanceMetrics();
            
            AlertDialog.show({
                message: '查询分析完成'
            });
        } catch (error) {
            this.errorMessage = '分析失败: ' + error.message;
        } finally {
            this.isLoading = false;
        }
    }
    
    recommendIndexes() {
        if (!this.tableName.trim() || this.queryPatterns.length === 0) {
            this.errorMessage = '请输入表名和查询模式';
            return;
        }
        
        this.isLoading = true;
        
        try {
            this.optimizer.recommendIndexes(this.tableName, this.queryPatterns);
            this.indexRecommendations = this.optimizer.getIndexRecommendations();
        } catch (error) {
            this.errorMessage = '推荐失败: ' + error.message;
        } finally {
            this.isLoading = false;
        }
    }
    
    generateReport() {
        this.isLoading = true;
        
        try {
            this.report = this.optimizer.generateOptimizationReport();
        } catch (error) {
            this.errorMessage = '生成报告失败: ' + error.message;
        } finally {
            this.isLoading = false;
        }
    }
    
    getPriorityColor(priority: string): string {
        switch (priority) {
            case 'HIGH': return '#F44336';
            case 'MEDIUM': return '#FF9800';
            case 'LOW': return '#4CAF50';
            default: return '#999999';
        }
    }
    
    getIndexTypeLabel(indexType: string): string {
        return indexType === 'SINGLE' ? '单列索引' : '复合索引';
    }
    
    build() {
        Column() {
            // 顶部标题
            Text('数据库查询优化工具')
                .fontSize(24)
                .fontWeight(FontWeight.Bold)
                .margin({ top: 20, bottom: 20 })
            
            // 标签页
            Tabs({ barPosition: BarPosition.Start }) {
                TabContent() {
                    Column() {
                        Text('分析查询')
                            .fontSize(14)
                            .fontWeight(FontWeight.Bold)
                            .margin({ bottom: 15 })
                        
                        Text('SQL查询语句:')
                            .fontSize(12)
                            .margin({ bottom: 5 })
                        TextInput({ placeholder: 'SELECT * FROM users WHERE age > 18' })
                            .value(this.querySQL)
                            .onChange((value: string) => {
                                this.querySQL = value;
                            })
                            .height(60)
                            .padding(10)
                            .border({ width: 1, color: '#cccccc' })
                            .margin({ bottom: 15 })
                        
                        Row() {
                            Column() {
                                Text('执行时间(ms):')
                                    .fontSize(12)
                                    .margin({ bottom: 5 })
                                TextInput({ placeholder: '150' })
                                    .type(InputType.Number)
                                    .value(this.executionTime.toString())
                                    .onChange((value: string) => {
                                        this.executionTime = parseInt(value) || 150;
                                    })
                                    .height(40)
                                    .padding(10)
                                    .border({ width: 1, color: '#cccccc' })
                            }
                            .flex(1)
                            
                            Column() {
                                Text('扫描行数:')
                                    .fontSize(12)
                                    .margin({ bottom: 5 })
                                TextInput({ placeholder: '50000' })
                                    .type(InputType.Number)
                                    .value(this.rowsScanned.toString())
                                    .onChange((value: string) => {
                                        this.rowsScanned = parseInt(value) || 50000;
                                    })
                                    .height(40)
                                    .padding(10)
                                    .border({ width: 1, color: '#cccccc' })
                            }
                            .flex(1)
                            .margin({ left: 10 })
                        }
                        .margin({ bottom: 15 })
                        
                        Row() {
                            Column() {
                                Text('返回行数:')
                                    .fontSize(12)
                                    .margin({ bottom: 5 })
                                TextInput({ placeholder: '30000' })
                                    .type(InputType.Number)
                                    .value(this.rowsReturned.toString())
                                    .onChange((value: string) => {
                                        this.rowsReturned = parseInt(value) || 30000;
                                    })
                                    .height(40)
                                    .padding(10)
                                    .border({ width: 1, color: '#cccccc' })
                            }
                            .flex(1)
                            
                            Column() {
                                Text('是否使用索引:')
                                    .fontSize(12)
                                    .margin({ bottom: 5 })
                                Toggle({ type: ToggleType.Checkbox, isOn: this.indexUsed })
                                    .onChange((isOn: boolean) => {
                                        this.indexUsed = isOn;
                                    })
                                    .height(40)
                            }
                            .flex(1)
                            .margin({ left: 10 })
                        }
                        .margin({ bottom: 15 })
                        
                        Button('分析查询')
                            .width('100%')
                            .height(40)
                            .margin({ bottom: 15 })
                            .onClick(() => {
                                this.analyzeQuery();
                            })
                            .enabled(!this.isLoading)
                        
                        if (this.errorMessage) {
                            Text(this.errorMessage)
                                .fontSize(12)
                                .fontColor('#F44336')
                                .margin({ bottom: 15 })
                        }
                    }
                    .padding(15)
                }
                .tabBar('📝 分析查询')
                
                TabContent() {
                    Column() {
                        if (this.metrics) {
                            Text('性能指标')
                                .fontSize(16)
                                .fontWeight(FontWeight.Bold)
                                .margin({ bottom: 15 })
                            
                            Row() {
                                Column() {
                                    Text('总查询数')
                                        .fontSize(11)
                                        .fontColor('#999999')
                                    Text(this.metrics.totalQueries.toString())
                                        .fontSize(18)
                                        .fontWeight(FontWeight.Bold)
                                        .fontColor('#2196F3')
                                        .margin({ top: 5 })
                                }
                                .flex(1)
                                .alignItems(HorizontalAlign.Center)
                                .padding(10)
                                .backgroundColor('#F5F5F5')
                                .borderRadius(5)
                                
                                Column() {
                                    Text('平均执行时间')
                                        .fontSize(11)
                                        .fontColor('#999999')
                                    Text(`${this.metrics.averageExecutionTime.toFixed(2)}ms`)
                                        .fontSize(16)
                                        .fontWeight(FontWeight.Bold)
                                        .fontColor('#4CAF50')
                                        .margin({ top: 5 })
                                }
                                .flex(1)
                                .alignItems(HorizontalAlign.Center)
                                .padding(10)
                                .backgroundColor('#F5F5F5')
                                .borderRadius(5)
                                .margin({ left: 10 })
                                
                                Column() {
                                    Text('索引使用率')
                                        .fontSize(11)
                                        .fontColor('#999999')
                                    Text(`${this.metrics.indexUsageRate.toFixed(2)}%`)
                                        .fontSize(18)
                                        .fontWeight(FontWeight.Bold)
                                        .fontColor('#FF9800')
                                        .margin({ top: 5 })
                                }
                                .flex(1)
                                .alignItems(HorizontalAlign.Center)
                                .padding(10)
                                .backgroundColor('#F5F5F5')
                                .borderRadius(5)
                                .margin({ left: 10 })
                            }
                            .margin({ bottom: 15 })
                            
                            Column() {
                                Row() {
                                    Text('平均扫描行数:')
                                        .fontSize(12)
                                    Text(this.metrics.averageRowsScanned.toFixed(0))
                                        .fontSize(12)
                                        .fontWeight(FontWeight.Bold)
                                        .fontColor('#2196F3')
                                }
                                .margin({ bottom: 10 })
                                
                                if (this.metrics.slowestQuery) {
                                    Row() {
                                        Text('最慢查询:')
                                            .fontSize(12)
                                        Text(`${this.metrics.slowestQuery.executionTime}ms`)
                                            .fontSize(12)
                                            .fontWeight(FontWeight.Bold)
                                            .fontColor('#F44336')
                                    }
                                    .margin({ bottom: 10 })
                                }
                                
                                if (this.metrics.fastestQuery) {
                                    Row() {
                                        Text('最快查询:')
                                            .fontSize(12)
                                        Text(`${this.metrics.fastestQuery.executionTime}ms`)
                                            .fontSize(12)
                                            .fontWeight(FontWeight.Bold)
                                            .fontColor('#4CAF50')
                                    }
                                }
                            }
                            .padding(10)
                            .backgroundColor('#F5F5F5')
                            .borderRadius(5)
                        } else {
                            Text('请先分析查询')
                                .fontSize(12)
                                .fontColor('#999999')
                        }
                    }
                    .padding(15)
                }
                .tabBar('📊 性能指标')
                
                TabContent() {
                    Column() {
                        if (this.suggestions.length > 0) {
                            Text('优化建议')
                                .fontSize(16)
                                .fontWeight(FontWeight.Bold)
                                .margin({ bottom: 15 })
                            
                            List() {
                                ForEach(this.suggestions, (suggestion: any) => {
                                    ListItem() {
                                        Column() {
                                            Row() {
                                                Text(suggestion.suggestionType)
                                                    .fontSize(12)
                                                    .fontWeight(FontWeight.Bold)
                                                    .flex(1)
                                                Text(suggestion.priority)
                                                    .fontSize(11)
                                                    .fontColor('#FFFFFF')
                                                    .fontWeight(FontWeight.Bold)
                                                    .padding({ left: 8, right: 8, top: 4, bottom: 4 })
                                                    .backgroundColor(this.getPriorityColor(suggestion.priority))
                                                    .borderRadius(3)
                                            }
                                            .margin({ bottom: 8 })
                                            
                                            Text(suggestion.description)
                                                .fontSize(12)
                                                .fontColor('#666666')
                                                .margin({ bottom: 8 })
                                            
                                            Text(`预期改进: ${suggestion.expectedImprovement.toFixed(1)}%`)
                                                .fontSize(11)
                                                .fontColor('#999999')
                                        }
                                        .padding(10)
                                        .border({ width: 1, color: '#eeeeee' })
                                        .borderRadius(5)
                                    }
                                }, (suggestion: any) => suggestion.id)
                            }
                        } else {
                            Text('暂无优化建议')
                                .fontSize(12)
                                .fontColor('#999999')
                        }
                    }
                    .padding(15)
                }
                .tabBar('💡 优化建议')
                
                TabContent() {
                    Column() {
                        Text('索引推荐')
                            .fontSize(14)
                            .fontWeight(FontWeight.Bold)
                            .margin({ bottom: 15 })
                        
                        Text('表名:')
                            .fontSize(12)
                            .margin({ bottom: 5 })
                        TextInput({ placeholder: 'orders' })
                            .value(this.tableName)
                            .onChange((value: string) => {
                                this.tableName = value;
                            })
                            .height(40)
                            .padding(10)
                            .border({ width: 1, color: '#cccccc' })
                            .margin({ bottom: 15 })
                        
                        Button('推荐索引')
                            .width('100%')
                            .height(40)
                            .margin({ bottom: 15 })
                            .onClick(() => {
                                this.recommendIndexes();
                            })
                            .enabled(!this.isLoading)
                        
                        if (this.indexRecommendations.length > 0) {
                            List() {
                                ForEach(this.indexRecommendations, (rec: any) => {
                                    ListItem() {
                                        Column() {
                                            Row() {
                                                Text(this.getIndexTypeLabel(rec.indexType))
                                                    .fontSize(12)
                                                    .fontWeight(FontWeight.Bold)
                                                    .flex(1)
                                                Text(rec.priority)
                                                    .fontSize(11)
                                                    .fontColor('#FFFFFF')
                                                    .fontWeight(FontWeight.Bold)
                                                    .padding({ left: 8, right: 8, top: 4, bottom: 4 })
                                                    .backgroundColor(this.getPriorityColor(rec.priority))
                                                    .borderRadius(3)
                                            }
                                            .margin({ bottom: 8 })
                                            
                                            Text(`列: ${rec.columns.join(', ')}`)
                                                .fontSize(12)
                                                .fontColor('#666666')
                                                .margin({ bottom: 8 })
                                            
                                            Text(`预期性能提升: ${rec.estimatedPerformanceGain.toFixed(1)}%`)
                                                .fontSize(11)
                                                .fontColor('#999999')
                                        }
                                        .padding(10)
                                        .border({ width: 1, color: '#eeeeee' })
                                        .borderRadius(5)
                                    }
                                }, (rec: any) => rec.id)
                            }
                        }
                    }
                    .padding(15)
                }
                .tabBar('🔍 索引推荐')
                
                TabContent() {
                    Column() {
                        Button('生成报告')
                            .width('100%')
                            .height(40)
                            .margin({ bottom: 15 })
                            .onClick(() => {
                                this.generateReport();
                            })
                        
                        if (this.report) {
                            Text('优化报告')
                                .fontSize(16)
                                .fontWeight(FontWeight.Bold)
                                .margin({ bottom: 15 })
                            
                            Column() {
                                Text(this.report.summary)
                                    .fontSize(12)
                                    .fontColor('#333333')
                                    .lineHeight(1.6)
                                    .margin({ bottom: 15 })
                            }
                            .padding(10)
                            .backgroundColor('#F5F5F5')
                            .borderRadius(5)
                            .margin({ bottom: 15 })
                            
                            if (this.report.nextSteps && this.report.nextSteps.length > 0) {
                                Text('后续步骤:')
                                    .fontSize(14)
                                    .fontWeight(FontWeight.Bold)
                                    .margin({ bottom: 10 })
                                
                                Column() {
                                    ForEach(this.report.nextSteps, (step: string, index: number) => {
                                        Row() {
                                            Text(`${index + 1}.`)
                                                .fontSize(12)
                                                .fontWeight(FontWeight.Bold)
                                                .margin({ right: 10 })
                                            Text(step)
                                                .fontSize(11)
                                                .flex(1)
                                        }
                                        .padding(10)
                                        .margin({ bottom: 8 })
                                        .backgroundColor('#E8F5E9')
                                        .borderRadius(5)
                                    }, (step: string, index: number) => index.toString())
                                }
                            }
                        }
                    }
                    .padding(15)
                }
                .tabBar('📈 报告')
            }
            .width('100%')
            .flex(1)
        }
        .padding(10)
        .width('100%')
        .height('100%')
    }
}

ArkTS代码说明:这个ArkTS实现展示了如何在OpenHarmony应用中集成数据库查询优化工具。通过使用标签页组件,用户可以在分析查询、查看性能指标、查看优化建议、查看索引推荐和生成报告之间切换。UI设计直观,提供了良好的用户体验。每个标签页都有不同的功能,用户可以全面地了解数据库查询的性能特性和优化方向。


优化指标详解

查询性能指标

执行时间:查询从开始到完成所需的时间。通常分为最小值、最大值、平均值等。执行时间是最直观的性能指标。

扫描行数:查询需要扫描的数据行数。扫描行数越少,性能越好。理想情况下,扫描行数应该等于返回行数。

返回行数:查询返回的结果行数。通常应该远小于扫描行数,这表示WHERE条件有效地过滤了数据。

索引使用率:使用索引的查询比例。索引使用率越高,整体查询性能越好。

优化效果指标

预期改进:实施优化建议后预期的性能改进百分比。

性能提升:实际实施优化后的性能改进百分比。

成本节省:通过优化节省的数据库资源成本。

索引指标

索引大小:索引占用的磁盘空间。索引越小,维护成本越低。

性能提升:创建该索引预期的性能提升百分比。

维护成本:索引对INSERT、UPDATE、DELETE操作的影响。


实战案例

案例1:电商平台订单查询优化

在电商平台中,订单查询是高频操作。通过分析发现,按用户ID和订单状态查询订单时,没有使用索引,导致每次查询都需要扫描数百万条记录。通过创建复合索引(user_id, status),查询性能提升了80%,扫描行数从500万降低到5000。

案例2:社交媒体用户信息查询优化

在社交媒体应用中,用户信息查询非常频繁。通过分析发现,按用户名查询用户时,虽然创建了索引,但由于查询条件使用了LIKE操作符,导致索引失效。通过改写查询条件,使用精确匹配,查询性能提升了60%。

案例3:金融系统交易记录查询优化

在金融系统中,交易记录查询需要支持多种过滤条件,如日期范围、金额范围、交易类型等。通过分析发现,缺少合适的索引导致查询性能低下。通过创建多个单列索引和复合索引,查询性能提升了70%,同时支持了更灵活的查询条件。

案例4:IoT系统传感器数据查询优化

在IoT系统中,需要查询大量传感器数据。通过分析发现,按时间范围和传感器ID查询数据时,返回行数远小于扫描行数。通过优化WHERE条件和创建合适的索引,查询性能提升了85%,同时降低了数据库的CPU消耗。


总结

数据库查询优化工具是现代应用开发中的重要工具。通过KMP框架和OpenHarmony操作系统的结合,我们可以实现一个功能完整、高效可靠的数据库查询优化工具。

这个工具不仅能够分析查询的执行效率,还能够自动识别性能问题、生成优化建议、推荐索引、生成详细报告。通过本文介绍的Kotlin实现、JavaScript编译和ArkTS调用,开发者可以快速构建自己的数据库性能分析系统。

在实际应用中,数据库查询优化的价值远不止于此。从性能提升到成本降低,从用户体验改进到系统稳定性提升,数据库查询优化都发挥着重要的作用。通过持续分析和优化,可以构建更加高效和可靠的系统。

掌握好数据库查询优化的方法和工具,对于提升系统性能和用户体验都有重要的帮助。通过这个工具的学习和使用,希望能够帮助开发者更好地理解和优化自己的数据库查询,构建更加高效和可靠的系统。欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐