web: Startseiten-Feed cachen + Index gegen Filesort der Feed-Query
Der Livewire-Feed lief auf jeder Startseiten-Impression ungecacht; seine ORDER-BY-published_at-Query kann wegen portal IN (…) keinen bestehenden Index zur Sortierung nutzen und filesortete ~10-20k Zeilen (live gemessen 2,3 s pro Aufruf — die Startseite blieb dadurch trotz Seitendaten-Cache bei 6-9 s TTFB). Zwei Maßnahmen: - Neuer Index (language, status, deleted_at, published_at): Backward Index Scan statt Filesort, Query 2 ms statt 2,3 s — greift auch für ungecachte Livewire-Interaktionen (Zeitraum-Filter, tiefe Seiten). - Feed-Seiten 1-3 laufen über WebPageCache (SWR wie die übrigen Seitendaten); gecacht werden nur items + total, der Paginator wird pro Request neu gebaut (keine Host-URLs des Cache-Erzeugers im Cache). Unbekannte timeframe-Werte aus der URL fallen auf 'all' zurück und erreichen weder Query noch Cache-Key. Der doppelte Gesamt-COUNT pro Request entfällt; der 'Mehr laden'-Zähler nutzt jetzt den gefilterten Total des Paginators. Lokal mit Live-Datenbestand: Startseite kalt 875 ms (vorher 2,5 s), warm 11 ms (vorher 72 ms). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
bd4ad855ba
commit
3d10cbf709
3 changed files with 151 additions and 15 deletions
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
/**
|
||||
* Index für den öffentlichen PM-Feed (Startseite): Die Feed-Query filtert
|
||||
* portal IN (…) — dadurch kann kein portal-geführter Index die Sortierung
|
||||
* `ORDER BY published_at DESC LIMIT n` bedienen und MySQL filesortet
|
||||
* ~10–20k Treffer pro Aufruf (live gemessen: 2,3 s statt 30 ms). Dieser
|
||||
* Index führt mit language/status/deleted_at (Gleichheit) und published_at
|
||||
* (Range + Order) → Index-Order-Scan, der nach n passenden Zeilen stoppt;
|
||||
* portal wird als Restfilter auf den wenigen gelesenen Zeilen geprüft.
|
||||
*/
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('press_releases', function (Blueprint $table): void {
|
||||
if (! $this->hasIndex('press_releases', 'press_releases_feed_order_idx')) {
|
||||
$table->index(
|
||||
['language', 'status', 'deleted_at', 'published_at'],
|
||||
'press_releases_feed_order_idx'
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('press_releases', function (Blueprint $table): void {
|
||||
if ($this->hasIndex('press_releases', 'press_releases_feed_order_idx')) {
|
||||
$table->dropIndex('press_releases_feed_order_idx');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private function hasIndex(string $table, string $indexName): bool
|
||||
{
|
||||
return in_array($indexName, array_column(Schema::getIndexes($table), 'name'), true);
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue