数据库查询优化 - OpenHarmony KMP性能提升关键

目录
概述
在现代应用开发中,数据库查询的性能直接影响整个系统的响应速度和用户体验。数据库查询优化是提升系统性能的重要手段,它通过分析查询执行计划、识别性能瓶颈、提供优化建议来帮助开发者写出高效的SQL语句。本文档介绍如何在 Kotlin Multiplatform (KMP) 框架下,结合 OpenHarmony 鸿蒙操作系统,实现一个功能完整的数据库查询优化工具。
数据库查询优化工具是一个综合性的性能分析平台,它不仅能够分析SQL查询的执行效率,还能够识别常见的性能问题、提供具体的优化建议、生成详细的优化报告。通过KMP框架的跨端能力,这个工具可以在Android、iOS、Web和OpenHarmony等多个平台上运行,为开发者提供了一个强大的数据库性能分析和优化工具。
数据库查询优化的重要性
数据库查询优化在现代应用开发中的重要性日益凸显:
- 性能提升:优化查询可以显著提升数据库响应速度,减少用户等待时间。
- 资源节省:高效的查询可以减少数据库的CPU、内存和磁盘IO消耗。
- 并发能力:优化查询可以提升数据库的并发处理能力,支持更多用户。
- 成本降低:通过优化查询,可以减少数据库服务器的需求,降低运营成本。
- 系统稳定:避免低效查询导致的数据库阻塞和系统崩溃。
工具的核心价值
数据库查询优化工具提供以下价值:
- 查询分析:分析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
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)