web-dev-qa-db-de.com

Post Meta vs separate Datenbanktabellen

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

Die im Codex angegebene Erklärung ist nicht detailliert:

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

27
Nassif Bourguig

Nun, wenn ich den Hut eines WP Skript-Kiddies nehme, wäre meine Antwort: 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 keine, die es wert sind, in Metatabellen verwendet zu werden. Also, wenn Sie den Datentyp XYZ speichern und hoffen, dass Sie alle Posts abfragen, die XYZ mit dem Wert 'abc' haben, nun ... viel Glück. (Sehen Sie sich alle Tickets für Benutzer/Rollen/Caps im Trac WP an, um eine Vorstellung davon zu bekommen, wie groß die Gefahr sein 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.

28

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

Am Beispiel von Woocommerce

In einem Geschäft mit ca. 30.000 Produkten werden durchschnittlich ca. 40 Post-Metas (Attribute und alles) pro Produkt und 5 Produktbilder pro Produkt angezeigt. Dies bedeutet, dass für jedes Bild ca. 4 Bildmetas vorhanden sind:

30.000 Produkte x 40 Meta je = 1.200.000 Zeilen in wp_postmeta

+

30.000 Produkte x je 5 Bilder x je 4 Bildmeta = 600.000 Zeilen in wp_postmeta

Bei nur 30.000 Produkten haben Sie also 1.800.000 Zeilen in 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
  • die wp_postmeta-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'

abfrage, die Versandort aus allen Bestelldetails auswählt kommt in satten ~ 3 Sekunden auf einem dedizierten Einstiegsserver, selbst wenn es 5-10 Bestellungen gibt . Dies liegt daran, dass die Abfrage in einer wp_postmeta-Tabelle 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 und ein paar anderen Meta-Werten abruft. 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 mit normalen Mitteln 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_postmeta table wird langsam sein, wann immer es fertig ist. Auf dem Server, auf dem ich die unten implementierte Lösung getestet habe, wurden all diese ordnungsgemäß installiert und konfiguriert und optimiert, und die Website funktionierte für nicht angemeldete Benutzer oder häufig gestellte Fragen ohne Probleme, 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 Benutzer, Caching-Plugins oder andere Hilfsprogramme die tatsächlichen Daten aus der Datenbank abrufen wollten, um sie zwischenzuspeichern, oder irgendetwas 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. Also habe ich das EAV-Format in ein horizontales, flaches relationales Format umgewandelt. Ich hatte auch das Plugin, um Postmeta aus allen verschobenen Produkten aus der Tabelle wp_postmeta zu löschen.

Während ich dabei bin, habe ich auch Anhangpostmetas und alle Metas anderer Posttypen in ihre eigenen Tabellen verschoben.

Dann habe ich mich in den Filter get_ (post_type) _meta eingebunden, um den Abruf von Metadaten zu überschreiben und sie aus neuen benutzerdefinierten Tabellen bereitzustellen.

Jetzt dauert die gleiche Abfrage von früher, für deren Abruf von wp_postmeta ~ 3 Sekunden benö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 die EAV-Tabelle bei der 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 Unmenge von Daten zu haben, und - Gott verbietet es - diese Daten abzufragen/zu durchsuchen, um die Tabelle wp_postmeta 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 viele 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.

3
unity100

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. 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 Plugin-Einstellungen den Aufruf get_option () API - 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.

2
Dan Smart

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 array['key2'] = 'val 2' abfragen möchten, muss 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 var = val speichern, kann wp 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

1
Daithí

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 habe dies getan, weil ich einerseits wollte, dass Benutzer die WordPress-Site bearbeiten, indem sie neue Farmville-Daten eingeben, z. "eine kuh kostet 10 münzen" ABER von der integrationsseite: WENN sich das xml ändert, kostet die kuh jetzt "20 münzen" (über das front-end-bearbeitungs-plugin), die als option danach angegeben würden: so dass entweder die XML OR der Benutzer hatte Recht (Art Wiki-System).

Hier ist ein Beispiel, wenn Sie beide verwenden.

0
edelwater