guides/directory-data-model.html

DAS DATENMODELL

Wie ich das Schema für eine Verzeichnisseite im sechsstelligen Maßstab gestalte. Entitäten, Attribute, Slugs, Indizes und die Entwurfsentscheidungen, die sich zusammensetzen.

DAS DATENMODELL

← Blog All posts in this topic

Die Schemataentscheidungen, die sich zusammensetzen

Eine Verzeichnisseite bei 28.000 Zeilen (HostList.io) oder 137.000 Zeilen (Not Another Sunday) gelingt oder scheitert an Schemataentscheidungen, die in der ersten Woche getroffen werden. Die Entscheidungen, die am meisten zählen: wie Entitäten normalisiert werden, wie Attribute gespeichert werden, wie Slugs generiert werden, was indiziert wird.

Jede dieser Entscheidungen ist in kleinem Maßstab reversibel und prohibitiv teuer, um im sechsstelligen Maßstab zu beheben. Treffen Sie sie früh richtig.

Entitäten, Attribute, Verbindungen

Eine Entitätstabelle mit einer Masterzeile pro Unternehmen, Ort oder Produkt. Stabiler UUID-Primärschlüssel, eine Spalte pro intrinsisches Attribut (Name, Gründungsjahr, Primärmarkt). Vermeiden Sie, Attribute in JSON-Spalten auf dieser Schicht zu quetschen; sie sollten als Spalten erster Klasse abfragbar sein.

Eine Attributtabelle pro orthogonaler Achse. categories (jede Zeile ist eine Kategorie), regions (jede Zeile ist eine Region), price_tiers (jede Zeile ist eine Stufe). Dies sind die Dimensionen, entlang derer Entitäten gruppiert werden.

Viele-zu-Viele-Beziehungen über Verknüpfungstabellen: entity_categories, entity_regions, entity_features. Speichere nie kommagetrennte Kategorielisten in der entities-Tabelle; die Verknüpfungstabellen sind das, was Filterung, Auflistung und Zählung schnell macht.

Slugs sind für immer

Sobald eine Verzeichnisseite von Google indexiert wird, sollte sich der Slug nicht ändern. Verwende deterministische Slug-Generierung aus dem Entitätsnamen mit Kollisionsbehandlung über numerisches Suffix: nginx-hosting, nginx-hosting-2 wenn eine Kollision auftritt.

Führe eine separate slug_history-Tabelle, die jeden historischen Slug auf den aktuellen kanonischen Slug abbildet. Wenn ein Entitätsname geändert werden muss (Korrektur, Rebrand), wird der neue kanonische Slug generiert, der alte Slug trägt sich in die History-Tabelle ein, und eine permanente 301-Umleitung wird automatisch eingerichtet.

Die Kosten für falsche Slug-Stabilität auf einer 28K-Zeilen-Site sind katastrophal: Jede Umleitungskette, die du erstellst, ist eine kleine Ranking-Erosion, und es gibt keine guten nachträglichen Lösungen.

Indexierbarkeit auf Zeilenebene

Füge der entities-Tabelle eine boolesche Spalte indexable hinzu, Standard true, mit Logik, die sie auf false setzt, wenn die Entität nicht die Qualitätsschwellen erfüllt (unzureichend einzigartiger Inhalt, fehlende erforderliche Attribute, keine eingehenden internen Links).

Die Sitemap-Abfrage filtert nach indexable = true. Der Seiten-Renderer fügt noindex-Meta hinzu, wenn indexable = false. Beide werden aus der gleichen Spalte abgeleitet, sodass sie atomar synchron bleiben.

Auf HostList.io sind etwa 18K von 28K Entitäten zu einem beliebigen Zeitpunkt indexierbar. Die anderen 10K sind crawlbar, aber nicht indexierbar, was die indexierte Fläche sauber hält und die restlichen indexierten Seiten stärker macht.

Indizes, die zählen

Index auf slug für das Page-Render-Lookup. Index auf (indexable, last_updated_at) für die Sitemap-Query. Index auf (category_id, indexable) auf der Junction-Tabelle für Category-Listing-Pages. Index auf (region_id, indexable) für regionale Seiten.

Bei sechsstelliger Zeilengröße dauert eine nicht-indizierte Page-Render-Query Sekunden. Mit korrekten Indizes dauert sie Millisekunden. Der Build-Time-Impact verschärft sich: 28K Page Renders bei je 100ms sind 47 Minuten; bei je 10ms sind es 5 Minuten.

Führe EXPLAIN ANALYZE auf jeder Page-Render-Query im großen Maßstab aus. Der Standard-Query-Planner liegt bei verzeichnisförmigen Joins häufiger daneben, als man erwarten würde.

WHEN YOU ARE READY TO TALK