web-dev-qa-db-ja.com

メタテーブルと個別のデータベーステーブルのポスト

データストレージを必要とするプラグインを開発するとき、ある方法を使うことの長所と短所は何ですか?

コーデックスに示されている の説明 は詳細ではありません。

しかし、まったく新しいテーブルに飛び込む前に、プラグインのデータをWordPressのPost Meta(別名Custom Fields)に保存することでうまくいくかどうか検討してください。ポストメタが好ましい方法です。可能な限り実用的に使用してください。

27
Nassif Bourguig

さて、私がWPスクリプトキディの帽子を握るならば、私の答えはこうなるでしょう:常にpost_metaを使ってください。

しかし、私はデータベースに関することを2、3知っているので、私の答えは:決して、決して、決してあなたが問い合わせる必要があるかもしれないデータを保存するためにEAV(別名post_metaテーブル)を使用することです。

インデックスの面では、メタテーブルで使う価値のあるものは基本的にありません。そのため、データ型XYZを格納していて、XYZを持つすべての投稿に'abc'の値を使用してクエリを実行することを望んでいるのであれば、幸運です。 (WP tracのすべてのusers/roles/caps関連チケットを見て、それがどれほど嬉しいかを知るために。)

結合の面では、結合基準が複数ある場合にオプティマイザがクエリを分析するのではなく一般的なアルゴリズムを使用することを決定した制限にすぐに衝突します。

したがって、いいえ、いいえ、いいえ、いいえ。絶対にしないでください、絶対にeverメタを使用しないでください。格納しているものが見かけ上のもので、クエリ基準の一部になることは決してありません。

それはあなたのアプリに分割されます。たとえば、映画監督の誕生日を保存するのであれば、大したことではありません。あなたが望むすべてのメタを使用してください。しかし、映画の発売日などを保存している場合は、別のテーブルを使用せず(またはpostsテーブルに列を追加して)、その列にインデックスを追加するのが賢明です。

28

もしあなたのプラグインがたくさんのデータを持っているのであれば、wp_postmetaを使うことは、以下に示されるように良い考えではありません:

例としてWoocommerceを取ります。

約30,000の商品がある店舗で、商品ごとに平均約40の投稿メタ(属性とすべて)、商品ごとに5つの商品画像があるとします。

3万製品×40メタ各= wp_postmetaに1,200,000行

+

30,000製品x 5イメージ各x 4イメージメタ各= 600,000行(wp_postmeta)

そのため、わずか30,000の製品で、wp_postmetaに1,800,000の行があると見ています。

商品や商品画像にさらにプロパティを追加すると、この数が増えます。

それに関する問題は2つあります。

  • 自己結合はMySQLでは非常に高価です
  • それ以降のmysqlバージョンを使用していない限り、wp_postmetaテーブルはインデックス付けされません(すなわち、meta_valueにFULLTEXTインデックスがありません)。

実際の事例から例を挙げます。

SELECT meta_value from wp_postmeta WHERE meta_key LIKE '_shipping_city'

すべての注文の詳細から配送都市を選択するクエリ - 5〜10の注文があってもエントリレベルの専用サーバーでなんと3秒で来る 。これは、ライブインストールで300万行を超えるwp_postmetaテーブルからクエリが実行されるためです。

このテーマはwp_postmetaからさまざまな要素(スライダー、いくつかのレビュー挿入物、他のいくつかのメタ)を取得するため、ホームページでさえかなり遅くなります。一般的な商品リストは非常に遅く、商品をリストする場合も検索は同様に遅くなります。

これを通常の方法で修正することはできません。サーバーにElastic Searchを入れてWordpressでElastic Searchプラグインを使用することも、redis/memcachedを使用することも、優れたページキャッシュプラグインを使用することもできますが、結局のところ基本的な問題は残ります。 wp_postmetaテーブルは、実行されるたびに遅くなります。私が以下で実装したソリューションをテストしたサーバーでは、これらすべてが適切にインストールおよび設定され、最適化されています。

しかし、ログインしているユーザーが一般的に行われていないこと、またはcrons、キャッシングプラグイン、またはその他のユーティリティがdbから実際のデータを取得してキャッシュに入れようとしたり、その他の処理を実行しようとした瞬間、状況は遅くなりました。

だから私は他の何かを試してみました:

私は、コードによって生成されたカスタムテーブルにすべての製品メタ(ポストタイプの製品の場合はpostmeta)を取り込むための小さなプラグインをコーディングしました。このプラグインは各投稿のすべてのメタを取得し、列として各メタを追加して各行に値を挿入することによってテーブルを作成しました。だから、私はEAVフォーマットを水平でフラットなリレーショナルフォーマットに変えました。私はまた、wp_postmetaテーブルからすべての移動された製品からpostmetaを削除するためのプラグインを持っていました。

私はそれをしながら、私はまた添付ファイルpostmetaと他のすべての投稿タイプのメタをそれら自身のテーブルに移動しました。

それから私は新しいカスタムテーブルからそれらを提供するためにメタデータの検索をオーバーライドするためにget_(post_type)_metaフィルタにフックしました。

Wp_postmetaから取得するのに約3秒かかった、以前と同じクエリが、約0.006秒かかります。このサイトは、新規のWPインストールであるかのように動作します。

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

当然のことながら、Wordpressのやり方で物事をやるほうが良いです。それは実際のところ標準です。

しかし 、EAVテーブルがスケーリングにおいて非常に非効率的であることも明らかな知識です。それは無限に柔軟であなたがどんなデータでも保存することを可能にします、しかしあなたがその代金を払うのはパフォーマンスです。それは基本的なトレードオフです。

その文脈では、大量のデータを持っているつもりでいる誰かに言うのは難しいです - そしてwp_postmetaテーブルを確実に使うためにそのデータを検索/検索することは禁じられています。パフォーマンスのヒットは素晴らしいものになります。

カスタムテーブルを使用すると、データが蓄積されても十分な速度が維持されます。

Easy Digital Downloadsプラグインの作成者であるPippin Williamsが、プラグインのコーディングを始めたばかりの場合はカスタムテーブルを使用し、長期間使用するデータを作成する場合や大量のデータを積み上げる場合は、カスタムテーブルを使用すると述べました。カスタムテーブルをうまく設計すれば、より効率的にカスタムテーブルを使用できます。

他のすべてのプラグイン/アドオン開発者が、データを取得する前後にデータを操作するためにプラグインにフックする手段を持っていることを確認する必要があります。あなたがそうするならば、それからあなたはかなりしっかりしています。

3
unity100

それはあなたがしていることによります。 WP方法は十分に柔軟になるように設計されているので既存のテーブルを使用することですが、時々既存のテーブルに置くことができない新しいクラスのデータに達するでしょうカテゴリメタデータが必要な場合は、wp_termsmetaテーブルを作成することを選択できます。

ただし、通常は、存在するさまざまなテーブルにデータを非常に快適に格納できます。データの格納場所は、プラグインの動作によって異なります。

  • 一般的なプラグイン設定の場合は、 get_option() API呼び出しを使用します - これもキャッシュされます。
  • 個々の投稿に固有のプラグイン設定の場合は、 get_post_meta() を使用して投稿ごとのカスタムメタデータを使用します。これは通常あなたが必要とするもののためにたくさんあります。

キャッシングはWordPressに実装されており、応答時間も短縮されます。

2
Dan Smart

デニス100%に同意した。しかし、それを回避する方法があります。

クエリ対象の値にpost metaを使用する際の問題は、値が配列などの場合です。

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

これは直列化された文字列としてdbに格納されます。これは次のようになります。

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

array['key2'] = 'val 2'を使ってすべての投稿をクエリしたいときは、wpはarrayと呼ばれるすべてのメタエントリを取り出し、それを解凍してからテストし、次に次に進む必要があります。あなたのサイトが成功し、投稿、ページ、カスタム投稿などがたくさんある場合、これは間違いなくあなたのサーバーをダウンさせるでしょう。

解決策はプロジェクトに依存します、そしてあなたは理由を見るでしょう。あなたがvar = valとしてデータを保存することになっているならば、wpはあらゆるテストをアンパックするphpを持っていなくても検索することができるでしょう。上記のシナリオでこれを行うには、名前空間を使用してメタキーを保存します。

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

その後、val 2でkey 2を探していると、すぐにそれを引っ張ることができます。これはプロジェクト依存です。私の現在のプロジェクトでは、カスタム投稿ごとに格納するために約20種類のdataTypeを使用しているため、上記の例では膨大な数の投稿を期待していると見なして検索用の巨大なテーブルを作成します。したがって、そのシナリオではカスタムテーブルが唯一の方法です。

これが誰かに役立つことを願っています

1
Daithí

私のFarmVilleサイトのために:)私は両方をしましたが、私がそれを売ったのでそれを終えませんでした:

  1. Farmville xmlを読み、カスタムテーブルにデータをダンプしました
  2. WordPressでは、そのテーブルのすべてのフィールドに対してカスタムフィールドを自動的に作成しました
  3. テーブルまたは反対側のいずれかで値が変更された場合に何が起こるかを今すぐ心配してください。それらは継続的に同期する必要があるのでカスタムフィールドです。

これは、一方でユーザーに新しいファームヴィルデータを入力してワードプレスサイトを編集させることを望んだためです。しかし統合側からは「牛1個に10コインが必要」:xmlの変更に伴って牛は現在「フロントエンド編集プラグイン経由で」20コインを払うことになります。 XML ORユーザーは正しかった(一種のwikiシステム)。

それで、両方を使うときの例です。

0
edelwater