/** * 数据库性能测试脚本 * 用于验证索引优化效果 */ import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); interface TestResult { name: string; duration: number; recordCount: number; } async function measureQuery(name: string, queryFn: () => Promise): Promise { const start = Date.now(); const result = await queryFn(); const duration = Date.now() - start; const recordCount = Array.isArray(result) ? result.length : 1; console.log(` ✓ ${name}: ${duration}ms (${recordCount} 条记录)`); return { name, duration, recordCount }; } async function main() { console.log('🚀 开始性能测试...\n'); const results: TestResult[] = []; // ============================================ // 产品查询测试 // ============================================ console.log('📦 产品查询测试:'); results.push( await measureQuery('产品列表(无过滤)', async () => { return await prisma.product.findMany({ take: 20, }); }) ); results.push( await measureQuery('产品列表(软删除过滤)', async () => { return await prisma.product.findMany({ where: { deletedAt: null }, take: 20, }); }) ); results.push( await measureQuery('产品列表(部门+可见性)', async () => { const dept = await prisma.department.findFirst(); return await prisma.product.findMany({ where: { departmentId: dept?.id, visibility: 'TEAM', deletedAt: null, }, take: 20, }); }) ); results.push( await measureQuery('产品列表(按创建时间排序)', async () => { return await prisma.product.findMany({ where: { deletedAt: null }, orderBy: { createdAt: 'desc' }, take: 20, }); }) ); results.push( await measureQuery('产品统计(活跃产品数)', async () => { return await prisma.product.count({ where: { deletedAt: null }, }); }) ); // ============================================ // SKU 查询测试 // ============================================ console.log('\n📦 SKU 查询测试:'); results.push( await measureQuery('SKU 列表(按产品)', async () => { const product = await prisma.product.findFirst(); return await prisma.productSKU.findMany({ where: { productId: product?.id }, }); }) ); results.push( await measureQuery('SKU 列表(产品+状态)', async () => { const product = await prisma.product.findFirst(); return await prisma.productSKU.findMany({ where: { productId: product?.id, isActive: true, deletedAt: null, }, }); }) ); results.push( await measureQuery('SKU 统计(活跃 SKU 数)', async () => { return await prisma.productSKU.count({ where: { isActive: true, deletedAt: null, }, }); }) ); // ============================================ // 用户查询测试 // ============================================ console.log('\n👤 用户查询测试:'); results.push( await measureQuery('用户列表(按部门)', async () => { const dept = await prisma.department.findFirst(); return await prisma.user.findMany({ where: { departmentId: dept?.id }, }); }) ); results.push( await measureQuery('用户列表(部门+状态)', async () => { const dept = await prisma.department.findFirst(); return await prisma.user.findMany({ where: { departmentId: dept?.id, status: 'ACTIVE', }, }); }) ); results.push( await measureQuery('用户列表(按角色)', async () => { return await prisma.user.findMany({ where: { role: 'DESIGNER' }, }); }) ); results.push( await measureQuery('用户统计(活跃用户数)', async () => { return await prisma.user.count({ where: { status: 'ACTIVE' }, }); }) ); // ============================================ // 反馈查询测试 // ============================================ console.log('\n💬 反馈查询测试:'); results.push( await measureQuery('反馈列表(按产品)', async () => { const product = await prisma.product.findFirst(); return await prisma.feedback.findMany({ where: { productId: product?.id }, }); }) ); results.push( await measureQuery('反馈列表(产品+状态)', async () => { const product = await prisma.product.findFirst(); return await prisma.feedback.findMany({ where: { productId: product?.id, status: 'PENDING', }, }); }) ); results.push( await measureQuery('反馈列表(优先级+状态)', async () => { return await prisma.feedback.findMany({ where: { priority: 'HIGH', status: 'PENDING', }, }); }) ); results.push( await measureQuery('反馈统计(待处理数)', async () => { return await prisma.feedback.count({ where: { status: 'PENDING' }, }); }) ); results.push( await measureQuery('反馈统计(按状态分组)', async () => { return await prisma.feedback.groupBy({ by: ['status'], _count: true, }); }) ); // ============================================ // 操作日志查询测试 // ============================================ console.log('\n📝 操作日志查询测试:'); results.push( await measureQuery('日志列表(按用户)', async () => { const user = await prisma.user.findFirst(); return await prisma.activityLog.findMany({ where: { userId: user?.id }, take: 20, }); }) ); results.push( await measureQuery('日志列表(用户+时间排序)', async () => { const user = await prisma.user.findFirst(); return await prisma.activityLog.findMany({ where: { userId: user?.id }, orderBy: { createdAt: 'desc' }, take: 20, }); }) ); results.push( await measureQuery('日志列表(按类型)', async () => { return await prisma.activityLog.findMany({ where: { type: 'PRODUCT_CREATE' }, take: 20, }); }) ); results.push( await measureQuery('日志列表(类型+时间排序)', async () => { return await prisma.activityLog.findMany({ where: { type: 'PRODUCT_CREATE' }, orderBy: { createdAt: 'desc' }, take: 20, }); }) ); results.push( await measureQuery('日志统计(按类型分组)', async () => { return await prisma.activityLog.groupBy({ by: ['type'], _count: true, }); }) ); // ============================================ // 复杂查询测试 // ============================================ console.log('\n🔍 复杂查询测试:'); results.push( await measureQuery('产品详情(含 SKU)', async () => { const product = await prisma.product.findFirst(); return await prisma.product.findUnique({ where: { id: product?.id }, include: { skus: true, assemblySteps: true, panels: true, }, }); }) ); results.push( await measureQuery('用户详情(含部门和小组)', async () => { const user = await prisma.user.findFirst(); return await prisma.user.findUnique({ where: { id: user?.id }, include: { department: true, team: true, }, }); }) ); results.push( await measureQuery('部门树(含子部门)', async () => { return await prisma.department.findMany({ where: { parentId: null }, include: { children: { include: { children: true, }, }, }, }); }) ); // ============================================ // 性能总结 // ============================================ console.log('\n📊 性能总结:'); console.log('─'.repeat(60)); const avgDuration = results.reduce((sum, r) => sum + r.duration, 0) / results.length; const maxDuration = Math.max(...results.map((r) => r.duration)); const minDuration = Math.min(...results.map((r) => r.duration)); console.log(` 平均响应时间: ${avgDuration.toFixed(2)}ms`); console.log(` 最快查询: ${minDuration}ms`); console.log(` 最慢查询: ${maxDuration}ms`); const fastQueries = results.filter((r) => r.duration < 50).length; const mediumQueries = results.filter((r) => r.duration >= 50 && r.duration < 100).length; const slowQueries = results.filter((r) => r.duration >= 100).length; console.log(`\n 性能分布:`); console.log(` < 50ms: ${fastQueries} 个查询 (${((fastQueries / results.length) * 100).toFixed(1)}%)`); console.log(` 50-100ms: ${mediumQueries} 个查询 (${((mediumQueries / results.length) * 100).toFixed(1)}%)`); console.log(` > 100ms: ${slowQueries} 个查询 (${((slowQueries / results.length) * 100).toFixed(1)}%)`); console.log('\n─'.repeat(60)); if (avgDuration < 100) { console.log('✅ 性能优秀!平均响应时间 < 100ms'); } else if (avgDuration < 200) { console.log('⚠️ 性能良好,但有优化空间'); } else { console.log('❌ 性能需要优化'); } // 找出最慢的查询 const slowestQueries = results.sort((a, b) => b.duration - a.duration).slice(0, 5); console.log('\n🐌 最慢的 5 个查询:'); slowestQueries.forEach((r, i) => { console.log(` ${i + 1}. ${r.name}: ${r.duration}ms`); }); console.log('\n✅ 性能测试完成!'); } main() .catch((e) => { console.error('❌ 性能测试失败:', e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });