web-dev-qa-db-fra.com

Post meta vs tables de base de données séparées

Lors du développement de plug-ins nécessitant un stockage de données, quels sont les avantages et les inconvénients de l'utilisation d'une méthode ou d'une autre?

L'explication donnée dans le codex n'est pas détaillée:

Cependant, avant de vous lancer dans une nouvelle table, demandez-vous si le stockage des données de votre plug-in dans PostPress en WordPress (a.k.a. Custom Fields) fonctionnerait. Post Meta est la méthode préférée. utilisez-le quand c'est possible/pratique.

27
Nassif Bourguig

Eh bien, si je prends le chapeau d'un script pour enfants WP, ma réponse serait: use post_meta, always.

Cependant, je connais quelque chose au sujet des bases de données, ma réponse est donc: ne jamais, jamais, jamais, utiliser un EAV (ou table post_meta) pour stocker des données que vous pourriez avoir besoin d'interroger.

Sur le plan de l'index, il n'y en a aucun qui vaille la peine d'être utilisé dans les méta-tables. Donc, si vous stockez le type de données XYZ et espérez que vous interrogez toutes les publications qui ont XYZ avec une valeur de 'abc', eh bien ... bonne chance. (Voir tous les billets relatifs aux utilisateurs/rôles/majuscules dans la trace WP pour vous donner une idée de son horreur.)

Au niveau de la jointure, vous atteignez rapidement la limite à laquelle l'optimiseur décide d'utiliser un algorithme générique au lieu d'analyser la requête lorsqu'il existe plusieurs critères de jointure.

Ainsi, non, non, non, non. Ne jamais, jamais, jamais utilisez une méta. Sauf si ce que vous stockez est esthétique et ne fera jamais partie d'un critère de requête.

Cela se résume à votre application. Si vous enregistrez, par exemple, la date de naissance d'un directeur de film, ce n'est pas grave. Utilisez une méta tout ce que vous voulez. Mais si vous stockez, par exemple, la date de sortie d'un film, vous ne devriez pas utiliser une table séparée (ou ajouter des colonnes à la table des publications) et ajouter un index à cette colonne.

28
Denis de Bernardy

Si votre plugin doit contenir BEAUCOUP de données, alors utiliser wp_postmeta n'est PAS une bonne idée, comme illustré ci-dessous:

En prenant Woocommerce comme exemple,

Dans un magasin avec environ 30 000 produits, supposons qu’il y aura en moyenne environ 40 posts méta (attributs et tout) par produit, 5 images de produit par produit, ce qui signifie qu’il y aura environ 4 méta-images pour chaque image:

30 000 produits x 40 méta chacun = 1 200 000 lignes dans wp_postmeta

+

30 000 produits x 5 images chacun x 4 méta d'image pour chacun = 600 000 lignes dans wp_postmeta

Donc, avec seulement 30 000 produits, vous envisagez de créer 1 800 000 lignes dans wp_postmeta.

Si vous ajoutez plus de propriétés à vos produits ou à vos images de produit, ce nombre se multipliera.

Le problème avec cela est double:

  • Les jointures sont très chères avec MySQL
  • la table wp_postmeta n'est pas indexée sauf si vous utilisez des versions ultérieures de mysql (c'est-à-dire pas d'index FULLTEXT pour meta_value)

Pour donner un exemple tiré d'un cas réel:

SELECT méta_value FROM wp_postmeta WHERE meta_key LIKE '_shipping_city'

query, qui sélectionne la ville d’expédition de tous les détails de la commande s’applique environ 3 secondes sur un serveur d’entrée de gamme même s’il ya 5 à 10 commandes . En effet, la requête est exécutée à partir d'une table wp_postmeta contenant environ 3 millions de lignes dans une installation dynamique.

Même la page d’accueil est assez lente, car le thème tire divers éléments de wp_postmeta - sliders, quelques encarts d’avis, quelques autres méta. En général, la liste des produits est très lente, de même que les recherches.

Vous ne pouvez pas résoudre ce problème par aucun moyen normal. Vous pouvez mettre Elastic Search sur votre serveur et utiliser un plugin Elastic Search dans Wordpress, vous pouvez utiliser redis/memcached, vous pouvez utiliser un bon plugin de cache page, mais à la fin, le problème fondamental restera - extraire toute quantité de données à partir d'une mémoire gonflée. La table wp_postmeta sera lente chaque fois que cela sera fait. Sur le serveur où j’ai testé la solution mise en œuvre ci-dessous, toutes ces applications ont été installées, configurées correctement et optimisées, et le site a fonctionné de manière satisfaisante pour les utilisateurs non connectés ou les requêtes fréquemment effectuées depuis l’installation des plugins de mise en cache.

Mais au moment où un utilisateur connecté essayait de faire quelque chose d’inhabituel ou que les logiciels crons, les plugins de mise en cache ou tout autre utilitaire voulaient extraire les données réelles de la base de données pour les mettre en cache ou faire autre chose, les choses devenaient lentes.

Alors j'ai essayé autre chose:

J'ai codé un petit plugin pour prendre toutes les méta du produit (postmeta pour un produit de type post) dans une table personnalisée générée par le code. Ce plugin a pris toutes les méta pour chaque publication et a créé une table en ajoutant chaque méta sous forme de colonnes et en insérant les valeurs dans chaque ligne. J'ai donc transformé le format EAV en un format relationnel horizontal et plat. J'ai également eu le plugin pour supprimer postmeta de tous les produits déplacés de la table wp_postmeta.

Pendant ce temps, j'ai aussi déplacé l'attachement postmeta et la méta de tous les autres types de post sur leurs propres tables.

Puis je me suis accroché au filtre get_ (post_type) _meta pour remplacer la récupération des métadonnées afin de les servir à partir de nouvelles tables personnalisées.

Maintenant, la même requête de plus tôt, qui a pris environ 3 secondes pour extraire de wp_postmeta prend environ 0,006 secondes. Le site se comporte désormais comme s'il s'agissait d'une nouvelle installation WP.

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

Naturellement, faire les choses à la manière Wordpress est préférable. C'est en fait la norme.

Cependant , il est également évident que la table EAV est très inefficace en termes de mise à l'échelle. Il est infiniment flexible et vous permet de stocker toutes les données, mais le prix que vous payez pour cela est la performance. C'est un compromis fondamental.

Dans ce contexte, il est difficile de dire à quelqu'un qui a l'intention de disposer de beaucoup de données et - ce qui est interdit - d'interroger/rechercher ces données pour utiliser la table wp_postmeta à coup sûr. La performance sera grande.

L'utilisation de vos tableaux personnalisés permettra à vos données de s'accumuler tout en restant suffisamment rapides.

Tout comme Pippin Williams, le créateur du plug-in Easy Digital Downloads, a mentionné qu'il utiliserait des tables personnalisées s'il commençait tout juste à coder son plug-in, si vous allez créer quelque chose qui sera utilisé pendant longtemps ou accumuler beaucoup de données, Il est plus efficace d’utiliser vos tables personnalisées si vous les concevez bien.

Vous devez vous assurer que tout autre développeur de plug-in/addon a les moyens de se connecter à votre plug-in pour manipuler vos données avant et après la récupération des données. Si vous faites cela, alors vous êtes assez solide.

3
unity100

Cela dépend de ce que vous faites. La méthode WP consiste à utiliser les tables existantes, car elles ont été conçues pour être suffisamment souples. Toutefois, vous atteignez parfois une nouvelle classe de données qui ne peut pas être placée dans une table existante, par exemple. si vous voulez des métadonnées de catégorie, vous pouvez choisir de créer une table wp_termsmeta.

Cependant, vous pouvez généralement stocker vos données assez facilement dans les différentes tables existantes, et l'emplacement où vous stockez vos données dépend de ce que fait votre plug-in.

  • Pour les paramètres généraux du plugin, utilisez l’appel get_option () API - il sera également mis en cache.
  • Pour les paramètres de plug-in qui concernent une publication particulière, utilisez les métadonnées personnalisées par publication avec get_post_meta () . C'est généralement suffisant pour ce dont vous avez besoin.

La mise en cache est implémentée dans WordPress pour accélérer également votre temps de réponse.

2
Dan Smart

d'accord avec denis 100%. Mais il y a un moyen de le contourner.

Le problème avec l'utilisation de la méta de publication pour les valeurs à interroger est lorsque les valeurs sont des tableaux, etc., comme ceci:

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

Cela est stocké dans la base de données en tant que chaîne sérialisée, qui ressemblera à ceci:

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

Donc, lorsque vous voulez interroger toutes les publications avec array['key2'] = 'val 2', alors wp doit extraire chaque méta entrée appelée array, la décompresser, puis la tester, puis passer à la suivante. Cela va définitivement arrêter votre serveur si votre site est réussi et a beaucoup de messages, pages, messages personnalisés, etc.

La solution dépend des projets et vous verrez pourquoi. Si vous deviez stocker les données sous la forme var = val, alors wp sera en mesure d'effectuer une recherche sans que php ne décompresse chaque test. Pour ce faire, dans le scénario ci-dessus, utilisez un espacement de nom et stockez les clés méta:

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

alors wp recherchant la clé 2 avec val 2 sera capable de la tirer tout de suite. Ce projet dépend cependant. Mon projet actuel repose sur environ 20 types de données différents à stocker avec chaque publication personnalisée. La création ci-dessus ne ferait donc que créer une table volumineuse dans laquelle effectuer des recherches. Nous prévoyons des centaines de milliers de publications. Donc, dans ce scénario, une table personnalisée est le seul moyen.

J'espère que cela aide quelqu'un

1
Daithí

Pour mon site FarmVille :) J'ai fait les deux mais je ne l'ai jamais fini car je l'ai vendu:

  1. J'ai lu le xml farmville et ai vidé les données dans un tableau personnalisé
  2. Dans WordPress, des champs personnalisés étaient automatiquement créés pour chaque champ de cette table (et quelques-uns en plus).
  3. Maintenant, inquiétez-vous de ce qui se passe si une valeur change dans la table ou de l'autre côté: le champ personnalisé, car ils doivent être synchronisés en permanence

Je l’ai fait parce que je voulais, d’une part, faire modifier le site wordpress par les utilisateurs en saisissant de nouvelles données, par exemple, de Farmville. "une vache coûte 10 pièces" MAIS du côté de l'intégration: SI un changement dans le xml ment, la vache coûte maintenant "20 pièces" (via le plugin d'édition front-end) qui serait donné en option après celle-ci XML OR l'utilisateur avait raison (sorte de système wiki).

Voici donc un exemple d'utilisation des deux.

0
edelwater