#!/usr/bin/env node /** * Script zur Analyse des knowledge_pkey Problems * * Prüft warum knowledge_pkey nicht verwendet wird */ import './config/loadEnv.js'; import { sequelize } from './utils/sequelize.js'; async function main() { try { console.log('🔍 Analyse knowledge_pkey Problem\n'); console.log('='.repeat(60) + '\n'); // Prüfe ob knowledge einen Primary Key hat const [pkInfo] = await sequelize.query(` SELECT a.attname as column_name, t.conname as constraint_name, t.contype as constraint_type FROM pg_constraint t JOIN pg_class c ON c.oid = t.conrelid JOIN pg_namespace n ON n.oid = c.relnamespace JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = ANY(t.conkey) WHERE n.nspname = 'falukant_data' AND c.relname = 'knowledge' AND t.contype = 'p'; `); console.log('📋 Primary Key Information:'); if (pkInfo.length > 0) { pkInfo.forEach(pk => { console.log(` Constraint: ${pk.constraint_name}`); console.log(` Spalte: ${pk.column_name}`); console.log(` Typ: ${pk.constraint_type === 'p' ? 'PRIMARY KEY' : pk.constraint_type}`); }); } else { console.log(' ⚠️ Kein Primary Key gefunden!'); } console.log(''); // Prüfe alle Indizes auf knowledge const [allIndexes] = await sequelize.query(` SELECT indexname, indexdef, idx_scan, idx_tup_read, idx_tup_fetch FROM pg_indexes LEFT JOIN pg_stat_user_indexes ON pg_stat_user_indexes.indexrelname = pg_indexes.indexname AND pg_stat_user_indexes.schemaname = pg_indexes.schemaname WHERE pg_indexes.schemaname = 'falukant_data' AND pg_indexes.tablename = 'knowledge' ORDER BY indexname; `); console.log('📊 Alle Indizes auf knowledge:'); allIndexes.forEach(idx => { console.log(`\n ${idx.indexname}:`); console.log(` Definition: ${idx.indexdef}`); console.log(` Scans: ${idx.idx_scan ? parseInt(idx.idx_scan).toLocaleString() : 'N/A'}`); console.log(` Zeilen gelesen: ${idx.idx_tup_read ? parseInt(idx.idx_tup_read).toLocaleString() : 'N/A'}`); }); console.log(''); // Prüfe Tabellenstruktur const [tableStructure] = await sequelize.query(` SELECT column_name, data_type, is_nullable, column_default FROM information_schema.columns WHERE table_schema = 'falukant_data' AND table_name = 'knowledge' ORDER BY ordinal_position; `); console.log('📋 Tabellenstruktur:'); tableStructure.forEach(col => { console.log(` ${col.column_name}: ${col.data_type} ${col.is_nullable === 'NO' ? 'NOT NULL' : 'NULL'}`); }); console.log(''); // Erklärung: Warum knowledge_pkey ungenutzt ist const pkUnused = allIndexes.find(i => i.indexname === 'knowledge_pkey' && (i.idx_scan == null || parseInt(i.idx_scan) === 0)); if (pkUnused) { console.log('💡 Warum knowledge_pkey (0 Scans) ungenutzt ist:'); console.log(' Alle Zugriffe filtern nach (character_id, product_id), nie nach id.'); console.log(' Der PK-Index wird nur für Eindeutigkeit/Referenzen genutzt, nicht für Lookups.'); console.log(' idx_knowledge_character_product deckt die tatsächlichen Queries ab.\n'); } // Prüfe ob Queries mit id (Primary Key) gemacht werden let idUsage = []; try { const [rows] = await sequelize.query(` SELECT query, calls, total_exec_time, mean_exec_time FROM pg_stat_statements WHERE query LIKE '%knowledge%' AND (query LIKE '%knowledge.id%' OR query LIKE '%knowledge%id%') ORDER BY calls DESC LIMIT 5; `); idUsage = rows; } catch (e) { console.log(' ℹ️ pg_stat_statements nicht verfügbar – keine Query-Statistik.\n'); } if (idUsage.length > 0) { console.log('🔍 Queries die knowledge.id verwenden:'); idUsage.forEach(q => { console.log(` Aufrufe: ${parseInt(q.calls).toLocaleString()}`); console.log(` Query: ${q.query.substring(0, 150)}...`); console.log(''); }); } await sequelize.close(); process.exit(0); } catch (error) { if (error.message.includes('pg_stat_statements')) { console.log(' ⚠️ pg_stat_statements ist nicht aktiviert oder nicht verfügbar\n'); } else { console.error('❌ Fehler:', error.message); console.error(error.stack); } await sequelize.close(); process.exit(1); } } main();