Post Meta vs separate Datenbanktabellen

29

Welche Vor- und Nachteile hat die Verwendung der einen oder anderen Methode bei der Entwicklung von Plugins, für die Datenspeicherung erforderlich ist?

Die Erklärung im Kodex ist nicht detailliert:

Bevor Sie mit einer neuen Tabelle beginnen, sollten Sie sich überlegen, ob das Speichern der Daten Ihres Plugins in WordPress 'Post Meta (auch bekannt als Custom Fields) funktionieren würde. Post-Meta ist die bevorzugte Methode. benutze es wenn möglich / praktisch.

Nassif Bourguig
quelle
Zu Ihrer Information: MB Custom Table ist ein Plugin, das Metadaten in benutzerdefinierten Tabellen anstelle der Post-Metatabelle von WP speichern kann.
Anh Tran

Antworten:

30

Nun, wenn ich den Hut eines WP-Skript-Kiddies nehme, würde meine Antwort lauten: benutze immer post_meta.

Da ich jedoch ein oder zwei Dinge über Datenbanken weiß, lautet meine Antwort: Verwenden Sie niemals jemals eine EAV (auch bekannt als post_meta-Tabelle), um Daten zu speichern, die Sie möglicherweise zum Abfragen benötigen.

Auf der Indexseite gibt es im Grunde genommen keine, die es wert sind, in Metatabellen verwendet zu werden. Wenn Sie also den Datentyp XYZ speichern und hoffen, dass Sie alle Posts mit dem Wert XYZ abfragen, na ja 'abc', viel Glück. (Sehen Sie sich alle Benutzer / Rollen / Caps-bezogenen Tickets im WP-Trac an, um eine Vorstellung davon zu bekommen, wie blutig es werden kann.)

Auf der Join-Seite stoßen Sie schnell an das Limit, an dem das Optimierungsprogramm einen generischen Algorithmus verwendet, anstatt die Abfrage zu analysieren, wenn mehrere Join-Kriterien vorhanden sind.

Also nein, nein, nein, nein. Verwenden Sie niemals, niemals, niemals ein Meta. Es sei denn, das, was Sie speichern, ist kosmetisch und wird niemals Teil eines Abfragekriteriums sein.

Es bricht auf Ihre App. Wenn Sie beispielsweise das Geburtsdatum eines Filmregisseurs speichern, ist das eine große Sache. Verwenden Sie ein Meta, was Sie wollen. Wenn Sie jedoch beispielsweise das Veröffentlichungsdatum eines Films speichern, wäre es verrückt, keine separate Tabelle zu verwenden (oder der Tabelle posts Spalten hinzuzufügen) und dieser Spalte einen Index hinzuzufügen.

Denis de Bernardy
quelle
1
Ja, die Plugins, die ich entwickle, verarbeiten benutzerdefinierte Daten wie Ereignisse, Nachrichten, Pressemitteilungen, Stellenangebote ... Von außerhalb von "WordPress World" ist die Verwendung von Tabellen keine Option. Aber der Rat vom WordPress-Codex ist ein bisschen verwirrend. Wie können serialisierte Datenblöcke gegenüber normalisierten / strukturierten / indizierten Daten bevorzugt werden?
Nassif Bourguig
1
Wenn Sie den durchschnittlichen WP-Entwickler fragen, antwortet er wahrscheinlich mit "Use a Meta" oder "Use a Taxonomy". Und ich stimme zu, bis zu dem Punkt, an dem Sie dagegen fragen müssen. Wenn ja, und ich glaube, es ist Ihr Fall, ist meine einzige Antwort, die Felder der Tabelle posts hinzuzufügen oder eine separate Tabelle vollständig zu erstellen. Andernfalls treten enorme Leistungsprobleme beim Abfragen und, was noch wichtiger ist, beim Sortieren von Knoten nach oben und nach unten auf.
Denis de Bernardy
1
Denis, könnten Sie das etwas näher erläutern? Ich finde es sehr informativ, würde aber gerne mehr Daten haben. Hat jemand Tests durchgeführt? Was genau sind die Hauptnachteile und -einschränkungen? Danke.
Wyck
6
@Denis - Ziemlich die leidenschaftliche Fürsprache gegen Postmeta, oder? Sie wissen, dass Sie entschieden gegen die Orthodoxie sind, und Sie werden aus der guten Gnade der Hohepriester der Kirche der Code-Poesie fallen, wenn Sie an solchen Gesprächen festhalten, nicht wahr? :-) Aber im Ernst, denkst du nicht, du übertreibst es ein bisschen? Es hängt wirklich davon ab, ob es Zehntausende von Metadatensätzen geben wird oder nicht. In vielen Fällen gibt es einfach nicht genug Datensätze, um die man sich Sorgen machen kann. Eine komplexe Site, die ich bereitstelle, hat ungefähr 10.000 Metadatensätze mit wenigen geplanten neuen Datensätzen, und es ist in Ordnung (zur Info, es ist kein Blog.)
MikeSchinkel
1
@Denis - Danke für die Kommentare. Und verstehen Sie mich nicht falsch, ich neige wahrscheinlich mehr zu Ihrer Perspektive als zu der Kombination aus 1.) einer einstündigen Debatte mit Matt im WordCamp Birmingham über die Vorzüge von Pods-ähnlichen Feldern und 2.) der Einfachheit von Meta Ich bin zurückgetreten, um mich auf andere Themen zu konzentrieren, die ich möglicherweise ändern könnte. Auf der WCB habe ich gemerkt, dass es sich nicht ändern wird, solange Matt das Sagen hat, weil Matt so verliebt in die Idee ist, weniger Tabellen zu haben, dass er sich nicht erlauben wird, die Nachteile der Indizierung auf einem 768-Byte zu erkennen Schlüssel. <Seufzer>
MikeSchinkel
5

Wenn Ihr Plugin VIELE Daten enthalten soll, ist die Verwendung von wp_postmetaKEINE gute Idee, wie unten gezeigt:

Beispiel WooCommerce: In einem Geschäft mit ca. 30.000 Produkten gibt es durchschnittlich ca. 40 Post-Meta (Attribute und alles) pro Produkt, also 5 Produktbilder pro Produkt, was ca. 4 Bild-Meta bedeutet für jedes Bild:

30.000 Produkte x 40 Meta je = 1.200.000 Zeilen in wp_postmeta

+

30.000 Produkte x 5 Bilder je x 4 Bildmeta für jeweils = 600.000 Zeilen in wp_postmeta

Also mit nur 30.000 Produkte betrachten Sie mit 1.800.000 Zeilen wp_postmeta.

Wenn Sie Ihren Produkten oder Produktabbildungen weitere Eigenschaften hinzufügen, multipliziert sich diese Zahl.

Das Problem dabei ist zweierlei:

  • Self-Joins sind mit MySQL sehr teuer
  • wp_postmetaDie Tabelle wird nur indiziert, wenn Sie neuere MySQL-Versionen verwenden (dh kein FULLTEXT-Index für meta_value).

Um ein Beispiel aus einem konkreten Fall zu geben:

SELECT meta_value FROM wp_postmeta WHERE meta_key LIKE '_shipping_city'

Dadurch wird die Versandstadt aus allen Bestelldetails mit einem Zeitsprung von ~ 3 Sekunden auf einem dedizierten Einstiegsserver ausgewählt, selbst wenn es 5-10 Bestellungen gibt . Dies liegt daran, dass die Abfrage in einer wp_postmetaTabelle ausgeführt wird, die in der Live-Installation ~ 3 Millionen Zeilen enthält.

Sogar die Homepage ist ziemlich langsam, da das Thema verschiedene Elemente aus wp_postmeta- Schiebereglern, ein paar Review-Einfügungen, ein paar anderen Metaelementen herausholt. Im Allgemeinen ist die Auflistung von Produkten sehr langsam, und die Suche bei der Auflistung von Produkten ist ähnlich langsam.

Sie können dies nicht auf normale Weise beheben. Sie können Elastic Search in Ihren Server einfügen und ein Elastic Search-Plugin in Wordpress verwenden, Sie können Redis / Memcached verwenden, Sie können ein gutes Seiten-Cache-Plugin verwenden, aber am Ende bleibt das grundlegende Problem bestehen - das Abrufen einer beliebigen Datenmenge von einem aufgeblähten Computer wp_postmetaDer Tisch wird langsam sein, wann immer er fertig ist. Auf dem Server, auf dem ich die unten implementierte Lösung getestet habe, wurden alle diese Komponenten ordnungsgemäß installiert und konfiguriert und optimiert, und die Website funktionierte für nicht angemeldete Benutzer oder häufig gestellte Fragen einwandfrei, seit das Caching von Plugins aktiviert wurde.

Aber in dem Moment, in dem ein angemeldeter Benutzer versuchte, etwas zu tun, was normalerweise nicht erledigt wurde, oder die Cron-, Caching-Plug-ins oder andere Dienstprogramme die tatsächlichen Daten aus der Datenbank abrufen wollten, um sie zwischenzuspeichern oder etwas anderes zu tun, wurden die Dinge langsam.

Also habe ich etwas anderes ausprobiert:

Ich habe ein kleines Plugin codiert, um alle Produkt-Metas (Postmetas für Post-Type- Produkte ) in eine benutzerdefinierte Tabelle zu übertragen, die durch Code generiert wurde. Dieses Plugin hat alle Metas für jeden Beitrag verwendet und eine Tabelle erstellt, indem jedes Meta als Spalten hinzugefügt und die Werte in jede Zeile eingefügt wurden. Ich habe das EAV-Format in ein horizontales, flaches relationales Format umgewandelt. Ich hatte auch das Plugin, um Postmeta von allen verschobenen Produkten aus der wp_postmetaTabelle zu löschen .

Während ich dabei bin, habe ich Postmeta für Anhänge und alle Metas anderer Posttypen in ihre eigenen Tabellen verschoben .

Dann habe ich den get_(post_type)_metaFilter aktiviert, um das Abrufen von Metadaten aus neuen benutzerdefinierten Tabellen zu überschreiben.

Nun dauert der Abruf derselben Abfrage von früher, für den ~ 3 Sekunden wp_postmetabenötigt wurden, ~ 0,006 Sekunden. Die Site verhält sich jetzt so, als wäre es eine neue WP-Installation.

....................

Natürlich ist es besser, Dinge mit Wordpress zu tun. Das ist eigentlich die Norm.

Allerdings ist es auch offensichtlich , dass Wissen EAV - Tabelle in Skalierung sehr ineffizient ist. Es ist unendlich flexibel und lässt Sie alle Daten speichern, aber der Preis, den Sie dafür bezahlen, ist die Leistung. Es ist ein grundlegender Kompromiss.

In diesem Zusammenhang ist es schwierig, jemandem mitzuteilen, der beabsichtigt, eine Menge Daten zu haben, und - Gott bewahre - diese Daten abzufragen / zu durchsuchen, um die wp_postmetaTabelle sicher zu verwenden. Der Leistungstreffer wird großartig sein.

Durch die Verwendung Ihrer benutzerdefinierten Tabellen können sich Ihre Daten häufen und bleiben dennoch schnell genug.

Genau wie Pippin Williams, der Schöpfer des Easy Digital Downloads-Plugins, erwähnt hat, dass er benutzerdefinierte Tabellen verwenden würde, wenn er gerade mit dem Codieren seines Plugins beginnen würde, wenn Sie etwas erstellen möchten, das für lange Zeit verwendet wird, oder wenn Sie eine Menge Daten stapeln möchten. Es ist effizienter, Ihre benutzerdefinierten Tabellen zu verwenden, wenn Sie sie gut entwerfen.

Sie müssen sicherstellen, dass sich jeder andere Plugin / Addon-Entwickler in Ihr Plugin einbinden kann, um Ihre Daten vor und nach dem Abrufen der Daten zu manipulieren. Wenn Sie das tun, dann sind Sie ziemlich solide.

unity100
quelle
1
Interessantes Zeug! Zu verdeutlichen ist, dass der erwähnte Filter "get_ (post_type) _meta" tatsächlich "get_ (meta-type) _metadata" heißt, wobei meta-type entweder post, comment oder user ist. Get_post_meta () durchläuft also den get_post_metadata-Filter, unabhängig vom Beitragstyp. Der Rückgabewert des Filters entspricht dem endgültigen Metawert.
Berend
get_ (meta-type) _metadata -> funktioniert in der Tat mit allen Beitragstypen, und die letzte Funktion, die besucht wird, ist get_post_metadata. Der Filter funktioniert jedoch, wenn Sie ihn trotzdem verwenden.
Unity100
2

Es hängt davon ab, was Sie tun. Die WP-Methode besteht darin, die vorhandenen Tabellen zu verwenden, da sie flexibel genug sind. Gelegentlich werden Sie jedoch eine neue Datenklasse erreichen, die nicht in eine vorhandene Tabelle eingefügt werden kann, z. B. wenn Sie Kategorie-Metadaten möchten können Sie eine wp_termsmeta-Tabelle erstellen.

Normalerweise können Sie Ihre Daten jedoch ganz bequem in den verschiedenen vorhandenen Tabellen speichern, und wo Sie Ihre Daten speichern, hängt davon ab, was Ihr Plugin tut.

  • Verwenden Sie für allgemeine Plug-in- Einstellungen den API-Aufruf get_option (). Dies wird auch zwischengespeichert.
  • Verwenden Sie für Plugin-Einstellungen, die sich auf einen bestimmten Beitrag beziehen , die benutzerdefinierten Metadaten pro Beitrag mit get_post_meta () . Dies ist in der Regel ausreichend für das, was Sie brauchen.

Caching ist in WordPress implementiert, um auch Ihre Antwortzeit zu beschleunigen.

Dan Smart
quelle
1

stimmte mit denis 100% überein. Aber es gibt einen Ausweg.

Das Problem bei der Verwendung des Post-Metas für abzufragende Werte liegt darin, dass es sich bei den Werten um Array-Werte usw. handelt.

array(
'key1' => 'val 1',
'key2' => 'val 2'
);

Dies wird in der Datenbank als serialisierter String gespeichert, der ungefähr so ​​aussieht:

{array["key1"]...{}...}

Wenn Sie also alle Beiträge mit abfragen möchten, muss array['key2'] = 'val 2'wp jeden Metaeintrag mit dem Namen array abrufen, entpacken, testen und zum nächsten wechseln. Dadurch wird Ihr Server definitiv heruntergefahren, wenn Ihre Site erfolgreich ist und viele Posts, Seiten, benutzerdefinierte Posts usw. enthält.

Die Lösung ist projektabhängig und Sie werden sehen, warum. Wenn Sie die Daten als speichern, kann var = valwp suchen, ohne PHP zu haben, um jeden einzelnen Test zu entpacken. Um dies in dem obigen Szenario zu tun, würden Sie einen Namespace verwenden und die Metaschlüssel speichern:

_array_key1 = 'val 1';
_array_key2 = 'val 2';

dann kann wp auf der Suche nach Schlüssel 2 mit Wert 2 diesen sofort abziehen. Dies ist jedoch projektabhängig. Mein aktuelles Projekt stützt sich auf ungefähr 20 verschiedene Datentypen, die mit jedem benutzerdefinierten Beitrag gespeichert werden, sodass mit den obigen Angaben nur eine umfangreiche Tabelle zum Durchsuchen erstellt wird, da wir mit Hunderttausenden von Beiträgen rechnen. In diesem Szenario ist eine benutzerdefinierte Tabelle der einzige Weg.

Hoffe das hilft jemandem

Daithí
quelle
0

Für meine FarmVille-Site :) Ich habe beides getan, aber es nie fertiggestellt, weil ich es verkauft habe:

  1. Ich habe die Farmville-XML gelesen und die Daten in einer benutzerdefinierten Tabelle abgelegt
  2. In WordPress hatte ich benutzerdefinierte Felder automatisch für jedes Feld in dieser Tabelle (und einige zusätzliche) gemacht
  3. Machen Sie sich jetzt Gedanken darüber, was passiert, wenn sich ein Wert in der Tabelle oder auf der anderen Seite ändert: im benutzerdefinierten Feld, da sie kontinuierlich synchronisiert werden müssen

Ich tat dies, weil ich zum einen wollte, dass Benutzer die WordPress-Site bearbeiten, indem sie neue Farmville-Daten eingeben, z. (über das Front-End-Bearbeitungs-Plugin), das danach als Option angegeben wird: damit entweder das XML ODER der Benutzer Recht hat (Art Wiki-System).

Hier ist ein Beispiel, wenn Sie beide verwenden.

Edelwasser
quelle