diff --git a/Dockerfile b/Dockerfile index e5141df..56fb97b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,4 +40,5 @@ FROM base AS production USER www-data # Create the SQLite database, migrate the tables, and seed the data -RUN php -r "file_exists('database/database.sqlite') || touch('database/database.sqlite');" +RUN php -r "file_exists('database/database.sqlite') || touch('database/database.sqlite');" \ + && php artisan db:tune-sqlite-reads diff --git a/app/Console/Commands/Install.php b/app/Console/Commands/Install.php index 9e7c401..290faa7 100644 --- a/app/Console/Commands/Install.php +++ b/app/Console/Commands/Install.php @@ -39,6 +39,8 @@ public function handle() $this->ensureDatabaseExists(); + $this->configureDatabase(); + $this->copyEnvExample(); $this->createAppKey(); @@ -56,6 +58,15 @@ protected function ensureDatabaseExists(): void file_exists(database_path('database.sqlite')) || touch(database_path('database.sqlite')); } + protected function configureDatabase(): void + { + try { + $this->call('db:tune-sqlite-reads'); + } catch (\Throwable $th) { + $this->fail('❌ There was an issue tuning SQLite reads, check the logs.'); + } + } + /** * Copy the .env.example file to .env. */ diff --git a/app/Console/Commands/TuneSqliteForReads.php b/app/Console/Commands/TuneSqliteForReads.php new file mode 100644 index 0000000..7641bd0 --- /dev/null +++ b/app/Console/Commands/TuneSqliteForReads.php @@ -0,0 +1,93 @@ +error('This command is only available for SQLite databases.'); + + return 1; + } + + $this->info('Tuning SQLite database for read performance...'); + + try { + // Enable WAL mode for better read performance + DB::statement('PRAGMA journal_mode=WAL'); + $this->info('✓ Journal mode set to WAL (Write-Ahead Logging)'); + + // Set cache size to 10,000 pages (approximately 40MB with default page size of 4KB) + DB::statement('PRAGMA cache_size=10000'); + $this->info('✓ Cache size set to 10,000 pages'); + + // Additional read optimizations + DB::statement('PRAGMA synchronous=NORMAL'); + $this->info('✓ Synchronous mode set to NORMAL'); + + DB::statement('PRAGMA temp_store=MEMORY'); + $this->info('✓ Temporary tables stored in memory'); + + DB::statement('PRAGMA mmap_size=268435456'); // 256MB + $this->info('✓ Memory-mapped I/O enabled (256MB)'); + + // Verify the settings + $this->newLine(); + $this->info('Current SQLite configuration:'); + + $journalMode = DB::selectOne('PRAGMA journal_mode'); + $this->line("Journal mode: {$journalMode->journal_mode}"); + + $cacheSize = DB::selectOne('PRAGMA cache_size'); + $this->line("Cache size: {$cacheSize->cache_size} pages"); + + $synchronous = DB::selectOne('PRAGMA synchronous'); + $this->line("Synchronous: {$synchronous->synchronous}"); + + $tempStore = DB::selectOne('PRAGMA temp_store'); + $this->line("Temp store: {$tempStore->temp_store}"); + + $mmapSize = DB::selectOne('PRAGMA mmap_size'); + $this->line('Memory-mapped size: '.number_format($mmapSize->mmap_size / 1024 / 1024, 1).'MB'); + + $this->newLine(); + $this->info('SQLite database has been successfully tuned for read performance!'); + $this->comment('Note: These settings are applied immediately. For persistent configuration across'); + $this->comment('application restarts, set the following in your .env file:'); + $this->comment('DB_JOURNAL_MODE=WAL'); + $this->comment('DB_CACHE_SIZE=10000'); + $this->comment('DB_SYNCHRONOUS=NORMAL'); + $this->comment('DB_TEMP_STORE=MEMORY'); + $this->comment('DB_MMAP_SIZE=268435456'); + + } catch (\Exception $e) { + $this->error('Failed to tune SQLite database: '.$e->getMessage()); + + return 1; + } + + return 0; + } +} diff --git a/config/database.php b/config/database.php index 125949e..c2ea294 100644 --- a/config/database.php +++ b/config/database.php @@ -38,8 +38,11 @@ 'prefix' => '', 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), 'busy_timeout' => null, - 'journal_mode' => null, - 'synchronous' => null, + 'journal_mode' => env('DB_JOURNAL_MODE', 'WAL'), + 'synchronous' => env('DB_SYNCHRONOUS', 'NORMAL'), + 'cache_size' => env('DB_CACHE_SIZE', 10000), + 'temp_store' => env('DB_TEMP_STORE', 'MEMORY'), + 'mmap_size' => env('DB_MMAP_SIZE', 268435456), // 256MB ], 'mysql' => [