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


29

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

コーデックスに与えられた説明が詳細に説明されていません。

ただし、まったく新しいテーブルにジャンプする前に、WordPressのPost Meta(別名カスタムフィールド)にプラグインのデータを保存できるかどうかを検討してください。ポストメタが推奨される方法です。可能な場合/実際に使用してください。


参考:MBカスタムテーブルは、WPのポストメタテーブルではなく、カスタムテーブルにメタデータを保存できるプラグインです。
アントラン

回答:


30

WPスクリプトキディの帽子をかぶった場合、私の答えは、常にpost_metaを使用することです。

しかし、私はたまたまデータベースについて知っているので、私の答えは次のとおりです。クエリする必要のあるデータを保存するために、EAV(別名post_metaテーブル)を決して使用しないでください。

インデックスの面では、基本的にメタテーブルで使用する価値はありません。したがって、データ型XYZを保存していて、XYZを持つすべての投稿に値を照会することを希望している場合は'abc'、幸運を祈ります。(WP tracのすべてのユーザー/ロール/キャップ関連チケットを参照して、それがどのように手に入らないかを理解してください。)

結合の最前線では、オプティマイザが複数の結合条件がある場合にクエリを分析する代わりに汎用アルゴリズムを使用することを決定する制限にすぐに衝突します。

したがって、いいえ、いいえ、いいえ、いいえ。今まで、これまでに、しないでください、これまでのメタを使用しています。格納するものが表面的なものであり、クエリ条件の一部にならない場合を除きます。

アプリに分類されます。たとえば、映画監督の生年月日を保存する場合は、大したことではありません。必要なメタをすべて使用します。しかし、たとえば映画のリリース日を保存している場合、別のテーブルを使用せず(または投稿テーブルに列を追加)、その列にインデックスを追加するのは簡単です。


1
はい、私が開発しているプラ​​グインは、イベント、ニュース、プレスリリース、求人などのカスタムデータを処理しています...「WordPress World」の外部から、テーブルを使用することは実際にはオプションではありません。しかし、WordPress Codexからのアドバイスは、少しわかりにくいです。正規化/構造化/インデックス化されたデータよりも、シリアル化されたデータの塊をどのように優先できますか?
ナシフブルギッグ

1
平均的なWP開発者に尋ねると、「メタを使用する」または「分類法を使用する」と答えるでしょう。そして、それに対してクエリを実行する必要がある点までは同意します。もしそうなら、そしてあなたの場合だと思いますが、私の唯一の答えは、投稿テーブルにフィールドを追加するか、完全に別のテーブルを作成することです。それ以外の場合は、クエリに関するパフォーマンスの問題が非常に大きくなり、さらに重要なことに、ノードのリストでは上位n個の並べ替えが必要になります。
デニスドバーナルディ

1
デニスはこれについてもう少し詳しく説明できますが、非常に有益であると思いますが、より多くのデータが大好きで、テストを行った人はいますか?、主な欠点と制限は何ですか?
ワイク

6
@Denis-ポストメタに対するかなりの情熱的な擁護、え?正統性に固く反対していることを知っているし、そのような話に固執すると、コード詩の教会の大祭司たちの良い恵みから落ちてしまうでしょう?:-)しかし、真剣にあなたは少し誇張すると思いませんか?数万件のメタレコードが存在するかどうかによって異なります。多くの場合、心配するだけの十分なレコードがありません。私が展開している複雑なサイトの1つには約10,000件のメタレコードがあり、新しいレコードはほとんど計画されていません。
それで問題あり

1
@Denis-コメントをありがとう。誤解しないでください。私はおそらくあなたの視点にもっと傾いていますが、1)WordCamp BirminghamでのPodのようなフィールドのメリットに関する1時間の議論と2.)メタのシンプルさの組み合わせ私は潜在的に変更する可能性のある他の問題に注意を集中するために辞任しました。WCBでは、マットが担当している限り変わらないことに気付きました(私の推測では)マットはテーブルが少ないという考えに夢中になっており、768バイトのインデックス作成の欠点を認識できないキー。<ため息>
MikeSchinkel

5

プラグインに大量のデータが含まれる場合、wp_postmeta以下に示すように、これを使用することはお勧めできません。

WooCommerceを例にとると、約30,000個の製品がある店舗では、製品ごとに平均で約40個のポストメタ(属性とすべて)、製品ごとに5個の製品イメージがあります。各画像について:

30,000製品x各40メタ= 1,200,000行 wp_postmeta

+

30,000個の製品x各5つの画像x各4つの画像メタ= 600,000行 wp_postmeta

そのため、たった30,000の製品で、1,800,000行のを探していますwp_postmeta

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

これには2つの問題があります。

  • MySQLの自己結合は非常に高価です
  • wp_postmeta後でmysqlのバージョン(版IEなしFULLTEXTインデックスを使用している場合を除き、テーブルがインデックス化されていませんmeta_value

実際のケースから例を挙げるには:

SELECT meta_value FROM wp_postmeta WHERE meta_key LIKE '_shipping_city'

これにより、すべての注文の詳細から出荷都市が選択されます。5〜10件の注文がある場合でも、エントリーレベルの専用サーバーでは約3秒で途方に暮れます。。。これはwp_postmeta、ライブインストールで最大300万行のテーブルからクエリが実行されるためです。

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

これを通常の方法で修正することはできません。サーバーにElastic Searchを配置し、WordpressでElastic Searchプラグインを使用し、redis / memcachedを使用し、適切なページキャッシュプラグインを使用できますが、最終的には根本的な問題が残ります-肥大化したデータからデータを取得するwp_postmetaテーブルは、実行されるたびに遅くなります。以下で実装したソリューションをテストしたサーバーに、これらはすべて適切にインストールおよび構成され、最適化され、サイトはログインしていないユーザーやキャッシュプラグインが起動されてからよく行われるクエリに対して良好に機能しました。

しかし、ログインしているユーザーが一般に行われていないことをしたり、cron、キャッシュプラグイン、またはその他のユーティリティがデータベースから実際のデータをフェッチしてキャッシュしたり、他のことをしたいと思った瞬間、物事は遅くなりました。

だから私は他のことを試しました:

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

その間、添付ファイルのポストメタと他のすべての投稿タイプのメタを独自のテーブルに移動しました。

次に、get_(post_type)_metaフィルターにフックしてメタデータの取得をオーバーライドし、新しいカスタムテーブルからメタデータを提供しました。

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

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

当然、Wordpressの方法で物事を行う方が優れています。それは実際に標準です。

ただし、EAVテーブルのスケーリングは非常に非効率的であることも明らかです。無限の柔軟性があり、あらゆるデータを保存できますが、その代価はパフォーマンスです。その基本的なトレードオフ。

その文脈では、大量のデータを持ちたいと思っている人に伝えることは困難であり、-神は禁じられています-そのデータをクエリ/検索して、wp_postmetaテーブルを確実に使用してください。パフォーマンスへの影響は大きいでしょう。

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

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

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


1
面白いもの!明確にする必要があるのは、前述の「get_(post_type)_meta」フィルターが実際に「get_(meta-type)_metadata」と呼ばれることです。メタタイプは投稿、コメント、またはユーザーです。したがって、get_post_meta()は、投稿タイプに関係なく、get_post_metadataフィルターを通過します。フィルターの戻り値は、最終的なメタ値にするものです。
ベレンド

get_(meta-type)_metadata->実際、すべての投稿タイプで動作し、実際にアクセスされる最終関数はget_post_metadataです。ただし、それでもフィルターを使用すると機能します。
unity100

2

それはあなたが何をしているかに依存します。WPの方法は既存のテーブルを使用することです。それらは十分な柔軟性を持つように設計されていますが、既存のテーブルに配置できない新しいクラスのデータに到達する場合があります。 、wp_termsmetaテーブルの作成を選択できます。

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

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

キャッシュはWordPress内に実装され、応答時間も短縮されます。


1

denis 100%と同意しました。しかし、それを回避する方法があります。

クエリ対象の値にポストメタを使用する場合の問題は、値が配列などの場合です。次のようになります。

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

これは、シリアル化された文字列としてdbに保存され、次のようになります。

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

だからすべての投稿をクエリしたいとき array['key2'] = 'val 2'、wpは配列と呼ばれるすべてのメタエントリをプルし、それをアンパックしてからテストし、次に移動する必要があります。これにより、サイトが成功し、多数の投稿、ページ、カスタム投稿などがある場合、サーバーが完全にダウンします。

ソリューションはプロジェクトに依存しており、その理由がわかります。データをaとして保存する場合var = val、wpはすべてのテストをアンパックするためのphpなしで検索できます。上記のシナリオでこれを行うには、いくつかのネームスペースを使用してメタキーを保存します。

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

次に、val 2でキー2を探すwpは、すぐにそれを引き出すことができます。ただし、これはプロジェクトに依存しています。私の現在のプロジェクトは、カスタムポストごとに約20の異なるdataTypesを格納することに依存しているため、上記では検索する巨大なテーブルを作成し、数十万のポストをどのように予想するかを確認します。そのため、このシナリオでは、カスタムテーブルが唯一の方法です。

これが誰かを助けることを願って


0

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

  1. Farmville XMLを読み取り、カスタムテーブルにデータをダンプしました
  2. WordPressでは、そのテーブル内のすべてのフィールドに対してカスタムフィールドが自動的に作成されました(および追加の)
  3. ここで、テーブルまたは反対側で値が変更された場合に何が起こるかを心配します。カスタムフィールドは継続的に同期する必要があるためです

これは、一方ではユーザーが新しいファームビルデータを入力してワードプレスサイトを編集できるようにしたかったためです。たとえば、統合側から「牛のコストは10コイン」ですが、XMLの変更があった場合、牛のコストは「20コイン」になります(フロントエンド編集プラグインを介して)オプションとして与えられます:XMLまたはユーザーのどちらかが正しいように(一種のwikiシステム)。

したがって、両方を使用する場合の例を次に示します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.