Pubblica meta vs tabelle di database separate


29

Quando si sviluppano plugin che richiedono l'archiviazione dei dati, quali sono i vantaggi e gli svantaggi dell'utilizzo di un metodo o di un altro?

La spiegazione fornita nel codice non è dettagliata:

Prima di saltare con una tabella completamente nuova, tuttavia, considera se la memorizzazione dei dati del tuo plugin in Post Meta (aka Campi personalizzati) di WordPress funzionerebbe. Post Meta è il metodo preferito; usalo quando possibile / pratico.


Cordiali saluti: MB Custom Table è un plug-in che può archiviare metadati in tabelle personalizzate anziché nella meta-tabella post di WP.
Anh Tran,

Risposte:


30

Bene, se prendo il cappello di un kiddie di script WP, la mia risposta sarebbe: usare post_meta, sempre.

Tuttavia, mi capita di conoscere una o due cose sui database, quindi la mia risposta è: mai, mai, mai, usare un EAV (aka la tabella post_meta) per archiviare i dati di cui potresti aver bisogno per interrogare.

Sul fronte dell'indice, praticamente non ne vale la pena usarli nelle meta table. Quindi, se stai memorizzando il tipo di dati XYZ e speri di interrogare tutti i post che hanno XYZ con un valore di 'abc', beh ... buona fortuna. (Vedi tutti i ticket relativi a utenti / ruoli / tappi nel trac WP per darti un'idea di quanto possa essere bello.)

Sul fronte dei join, si passa rapidamente al limite in base al quale l'ottimizzatore decide di utilizzare un algoritmo generico invece di analizzare la query in presenza di più criteri di join.

Quindi, no, no, no, no. Non usare mai mai un meta. A meno che ciò che stai memorizzando non sia cosmetico e non farà mai parte di un criterio di query.

Si rompe con la tua app. Se stai memorizzando, diciamo, la data di nascita di un regista, è un grosso problema. Usa un meta tutto quello che vuoi. Ma se stai memorizzando, diciamo, la data di uscita di un film, saresti pazzo a non usare una tabella separata (o aggiungere colonne alla tabella dei post) e aggiungere un indice a quella colonna.


1
Sì, i plugin che sto sviluppando gestiscono dati personalizzati come eventi, notizie, comunicati stampa, offerte di lavoro ... Dall'esterno di "WordPress World", l'utilizzo delle tabelle non è in realtà un'opzione. Ma i consigli del WordPress Codex sono un po 'confusi. Come si possono preferire blocchi di dati serializzati a dati normalizzati / strutturati / indicizzati?
Nassif Bourguig,

1
Se chiedi allo sviluppatore WP medio, probabilmente risponderà "usa una meta" o "usa una tassonomia". E sono d'accordo, fino al punto in cui è necessario interrogare contro di esso. In tal caso, e credo che sia il tuo caso, la mia unica risposta è, aggiungere i campi alla tabella dei messaggi o creare una tabella separata. Altrimenti ci si imbatte in enormi problemi di prestazioni quando si tratta di interrogazioni e, cosa ancora più importante per elenchi di nodi, ordinamento top-n.
Denis de Bernardy,

1
Denis saresti in grado di approfondire un po 'di più questo, lo trovo molto istruttivo ma mi piacerebbe qualche dato in più, qualcuno ha fatto dei test ?, quali sono esattamente i maggiori svantaggi e limitazioni, grazie.
Wyck,

6
@Denis - Abbastanza appassionato patrocinio contro postmeta, eh? Sai che stai andando fermamente contro l'ortodossia e cadrai dalle buone grazie dei sommi sacerdoti della chiesa della poesia del codice se persisti in simili discorsi, vero? :-) Ma sul serio non pensi di esagerare solo un po '? Dipende davvero se ci saranno decine di migliaia di meta record o meno. In molti casi semplicemente non ci sono abbastanza registrazioni di cui preoccuparsi. Un sito complesso che sto implementando ha circa 10.000 meta record con pochi nuovi record in programma, e va bene (a proposito, non è un blog.)
MikeSchinkel,

1
@Denis - Grazie per i commenti. E non fraintendermi, probabilmente mi spingerò molto di più verso la tua prospettiva, ma la combinazione di 1.) un dibattito di un'ora con Matt al WordCamp Birmingham sui meriti dei campi simili a Pods e 2.) la semplicità di meta è stato rassegnato a concentrare le mie attenzioni su altre questioni che potrei potenzialmente cambiare. Al WCB sono venuto a rendermi conto fintanto che Matt è in carica che non cambierà perché (suppongo sia) Matt è così innamorato dell'idea di un minor numero di tabelle che non si permetterà di riconoscere i lati negativi dell'indicizzazione su un 768 byte chiave. <sigh>
MikeSchinkel il

5

Se il tuo plugin avrà MOLTI dati, utilizzare wp_postmetaNON è una buona idea, come dimostrato di seguito:

Prendendo ad esempio WooCommerce, in un negozio con ~ 30.000 prodotti, ci sarà una media di, diciamo, ~ 40 post meta (attributi e tutto) per prodotto, 5 immagini di prodotto per prodotto, il che significa che ci saranno ~ 4 meta meta per ogni immagine:

30.000 prodotti x 40 meta ciascuno = 1.200.000 righe in wp_postmeta

+

30.000 prodotti x 5 immagini ciascuno x 4 meta immagine per ciascuno = 600.000 righe in wp_postmeta

Quindi, con solo 30.000 prodotti, stai visualizzando 1.800.000 di righe wp_postmeta.

Se aggiungi più proprietà ai tuoi prodotti o alle immagini dei tuoi prodotti, questo numero si moltiplica.

Il problema è duplice:

  • I self-join sono molto costosi con MySQL
  • wp_postmetala tabella non viene indicizzata a meno che non si utilizzino versioni successive di mysql (ovvero nessun indice FULLTEXT per meta_value)

Per dare un esempio da un caso reale:

SELECT meta_value FROM wp_postmeta WHERE meta_key LIKE '_shipping_city'

Questo seleziona la città di spedizione da tutti i dettagli dell'ordine arriva in un enorme ~ 3 secondi su un server dedicato entry level anche se ci sono 5-10 ordini . Questo perché la query viene eseguita da una wp_postmetatabella con ~ 3 milioni di righe nell'installazione live.

Anche la home page è piuttosto lenta, perché il tema estrae vari elementi da wp_postmeta- cursori, alcuni inserti di recensione, alcuni altri meta. In generale l'elenco dei prodotti è molto lento, le ricerche sono altrettanto lente quando si elencano i prodotti.

Non è possibile risolvere questo con qualsiasi mezzo normale. Puoi inserire Elastic Search nel tuo server e utilizzare un plug-in Elastic Search in Wordpress, puoi utilizzare redis / memcached, puoi utilizzare un buon plug-in di cache della pagina, ma alla fine rimarrà un problema fondamentale: recuperare qualsiasi quantità di dati da un gonfio wp_postmetala tabella sarà lenta, ogni volta che viene eseguita. Sul server in cui ho testato la soluzione che ho implementato di seguito, tutti questi sono stati installati e configurati correttamente e ottimizzati e il sito ha funzionato piacevolmente bene per gli utenti non registrati o per le domande più frequenti da quando sono iniziati i plug-in di cache.

Ma nel momento in cui un utente che ha effettuato l'accesso ha tentato di fare qualcosa che non era comunemente fatto o che i croni, i plug-in di cache o qualsiasi altra utilità volessero recuperare i dati effettivi dal db per memorizzarli nella cache o fare qualsiasi altra cosa, le cose sono andate piano piano.

Quindi ho provato qualcos'altro:

Ho codificato un piccolo plugin per portare tutti i meta del prodotto (postmeta per prodotto di tipo post ) su una tabella personalizzata generata dal codice. Questo plugin ha preso tutti i meta per ogni post e ha creato una tabella aggiungendo ogni meta come colonne e inserendo i valori in ogni riga. Ho trasformato il formato EAV in un formato relazionale orizzontale e piatto. Ho anche avuto il plug-in per eliminare postmeta da tutti i prodotti spostati dalla wp_postmetatabella.

Mentre ci sono, ho spostato l' allegato postmeta e tutti gli altri meta del tipo di post nelle proprie tabelle.

Quindi ho agganciato al get_(post_type)_metafiltro per sovrascrivere il recupero dei metadati per servirli da nuove tabelle personalizzate.

Ora la stessa query precedente, che impiegava ~ 3 secondi per il recupero, wp_postmetaimpiega ~ 0,006 secondi. Il sito ora si comporta come se fosse una nuova installazione di WP.

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

Naturalmente, fare le cose nel modo Wordpress è meglio. In realtà è la norma.

Tuttavia , è anche evidente che la tabella EAV è molto inefficiente nel ridimensionamento. È infinitamente flessibile e ti consente di archiviare qualsiasi dato, ma il prezzo che paghi per questo è la prestazione. È un compromesso fondamentale.

In quel contesto, è difficile dire a qualcuno che ha intenzione di avere un mucchio di dati e - dio non voglia - interrogare / cercare su quei dati per usare la wp_postmetatabella di sicuro. Il successo delle prestazioni sarà eccezionale.

L'uso delle tabelle personalizzate consentirà di accumulare i tuoi dati e rimanere comunque abbastanza veloci.

Proprio come Pippin Williams, il creatore del plug-in Easy Digital Downloads, ha menzionato che userebbe tabelle personalizzate se stesse appena iniziando a programmare il suo plug-in, se hai intenzione di creare qualcosa che verrà utilizzato per molto tempo o accumulare molti dati, è più efficiente usare le tue tabelle personalizzate se le progetti bene.

È necessario assicurarsi che qualsiasi altro sviluppatore di plug-in / addon disponga di mezzi per collegarsi al plug-in per manipolare i dati prima e dopo il recupero dei dati. Se lo fai, allora sei piuttosto solido.


1
Roba interessante! Una cosa da chiarire è che il citato filtro "get_ (post_type) _meta" è in realtà chiamato "get_ (meta-type) _metadata", dove meta-type è post, commento o utente. Quindi get_post_meta () passerà attraverso il filtro get_post_metadata, indipendentemente dal tipo di post. Il valore di ritorno del filtro è quello che vuoi che sia il meta valore finale.
Berend,

get_ (meta-type) _metadata -> effettivamente funziona con tutti i tipi di post, e infatti la funzione finale visitata è get_post_metadata. Tuttavia, il filtro funziona quando lo si utilizza comunque.
Unity100

2

Dipende da cosa stai facendo. Il modo WP consiste nell'utilizzare le tabelle esistenti, poiché sono state progettate per essere sufficientemente flessibili, tuttavia a volte raggiungerai una nuova classe di dati che non possono essere inseriti in una tabella esistente, ad esempio se desideri metadati di categoria , puoi scegliere di creare una tabella wp_termsmeta.

Tuttavia, di solito puoi archiviare i tuoi dati abbastanza comodamente nelle diverse tabelle esistenti e dove i tuoi dati dipendono da ciò che fa il tuo plugin.

  • Per le impostazioni generali del plug-in, utilizzare la chiamata API get_option () - anche questa verrà memorizzata nella cache.
  • Per le impostazioni del plug-in che riguardano un singolo post, quindi usa i metadati personalizzati per post con get_post_meta () . Questo di solito è sufficiente per quello che ti serve.

La memorizzazione nella cache è implementata in WordPress per velocizzare anche i tempi di risposta.


1

concordato con denis 100%. Ma c'è un modo per aggirarlo.

Il problema con l'utilizzo del post meta per i valori da interrogare è quando i valori sono di matrice ecc. Come questo:

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

Questo viene memorizzato nel db come una stringa serializzata, che avrà un aspetto simile al seguente:

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

Quindi quando vuoi interrogare tutti i post con array['key2'] = 'val 2'allora wp deve estrarre ogni meta voce chiamata array, decomprimerlo, quindi testarlo, quindi passare al successivo. Ciò eliminerà sicuramente il tuo server se il tuo sito ha successo e ha molti post, pagine, post personalizzati ecc.

La soluzione dipende dal progetto e capirai perché. Se dovessi memorizzare i dati come var = valallora allora wp sarà in grado di cercare senza dover php per decomprimere ogni singolo test. Per fare ciò nello scenario sopra, dovresti usare alcuni spazi dei nomi e memorizzare le meta-chiavi:

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

quindi wp cercando il tasto 2 con val 2 sarà in grado di estrarlo immediatamente. Questo progetto dipende però. Il mio progetto attuale si basa su circa 20 diversi tipi di dati da archiviare con ogni post personalizzato, quindi quanto sopra creerebbe semplicemente una tabella enorme da cercare, visto che ci aspettiamo centinaia di migliaia di post. Quindi, in quello scenario, una tabella personalizzata è l'unico modo.

Spero che questo aiuti qualcuno


0

Per il mio sito FarmVille :) Ho fatto entrambe le cose ma non l'ho mai finito perché l'ho venduto:

  1. Ho letto l'xml farmville e scaricato i dati in una tabella personalizzata
  2. In WordPress avevo campi personalizzati creati automaticamente per ogni campo di quella tabella (e alcuni extra)
  3. Ora preoccupati di cosa succede se un valore cambia nella tabella o dall'altra parte: il campo personalizzato poiché devono essere continuamente sincronizzati

L'ho fatto perché da un lato volevo che gli utenti modificassero il sito di wordpress inserendo nuovi dati farmville, ad esempio "una mucca costa 10 monete" MA dal lato dell'integrazione: SE un cambiamento nell'xml ment la mucca ora costa "20 monete" (tramite il plug-in di modifica front-end) che verrà fornito come opzione dopo di esso: in modo che l'XML o l'utente avesse ragione (una specie di sistema wiki).

Quindi ecco un esempio quando si usano entrambi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.