[WordPress] 多くの wp_postmeta、キー/値のテーブルに内部結合を使用してクエリの改善

スポンサーリンク

質問

働いている次のクエリを実行しているワードプレスの web サイトでは、このクエリは多くの内部結合をしているウェブサイトの読み込みに時間がかかり、多くのダウンし、同じ結果を生成するクエリを作成しようとしているを参照してくださいがまだない成功を収めた

ものでしたこれを行うには良い方法を知っているしたいと思います

SELECT *
FROM wp_posts
INNER JOIN wp_postmeta color ON wp_posts.ID = color.post_id 
INNER JOIN wp_postmeta transmission ON wp_posts.ID = transmission.post_id 
INNER JOIN wp_postmeta model ON wp_posts.ID = model.post_id 
INNER JOIN wp_postmeta brand ON wp_posts.ID = brand.post_id 

AND color.meta_key = 'color' 
AND color.meta_value = 'red' 
AND transmission.meta_key = 'transmission' 
AND transmission.meta_value = 'auto' 
AND model.meta_key = 'model' 
AND model.meta_value = 'model' 
AND brand.meta_key = 'brand' 
AND brand.meta_value = 'brand'

AND wp_posts.post_status = 'publish'
AND wp_posts.post_type = 'car'
ORDER BY wp_posts.post_title

ここでは説明の出力

+----+-------------+-----------+--------+-----------------------------+----------+---------+------------------------+------+----------------------------------------------+
| id | select_type | table         | type   | possible_keys               | key      | key_len | ref                          | rows | Extra                                        |
+----+-------------+-----------+--------+-----------------------------+----------+---------+------------------------+------+----------------------------------------------+
|  1 | SIMPLE      | color         | ref    | post_id,meta_key            | meta_key | 768     | const                        |  629 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | wp_posts      | eq_ref | PRIMARY,type_status_date,ID | PRIMARY  | 8       | tmcdb.color.post_id          |    1 | Using where                                  |
|  1 | SIMPLE      | brand         | ref    | post_id,meta_key            | post_id  | 8       | tmcdb.wp_posts.ID            |    4 | Using where                                  |
|  1 | SIMPLE      | transmission  | ref    | post_id,meta_key            | post_id  | 8       | tmcdb.color.post_id          |    4 | Using where                                  |
|  1 | SIMPLE      | model         | ref    | post_id,meta_key            | post_id  | 8       | tmcdb.transmission.post_id   |    4 | Using where                                  |
+----+-------------+-----------+--------+-----------------------------+----------+---------+------------------------+------+----------------------------------------------+

ここでワードプレス スキーマ


答え

あなたと思われる

car

のポストごとに 1 行を持つ結果セットを取得しようとしています。この記事では、それぞれの車のさまざまな属性を表示する場合、それらは

postmeta

で離れて隠しているようです

Pro ヒント: 決して

SELECT *

ソフトウェアで使用する絶対になぜそれをやっている知っている限り。特に多くの

JOIN

操作を含むクエリ、

SELECT *

多くの無意味な冗長な列を返します

そこはワードプレス

postmeta

の知っているクエリ デザイン トリック テーブル。特定の属性を取得したい場合これを行う:

 SELECT p.ID, p.post_title,
        color.meta_value AS color
   FROM wp_posts AS p
   LEFT JOIN wp_postmeta AS color ON p.ID = color.post_id AND 'color' = color.meta_key
  WHERE p.post_status = 'publish'
    AND /* etc etc */

超やってあなたが何をしようとしているときにこのパターンを理解することが重要です。

postmeta

はキー/値ストアと呼ばれるテーブルの特異な型なので、このパターンが必要です。ここ何が起こっているのですか?いくつかの事:

  1. このパターン uou を使用して各ポストは、
    posts

    テーブルからいくつかの列と、

    postmeta

    テーブルから特定の属性の 1 つの行を取得します

  2. 属性が不足している場合、あなたはまだ行を得るので、あなたは
    LEFT JOIN

    ing

    postmeta

    テーブル

  3. は、
    postmeta

    テーブルのエイリアス名を使用しています。ここでは、

    postmeta AS color

    です

  4. meta_key

    のセレクターを含むは (ここでは

    'color' = color.meta_key

    )、結合の

    ON

    状態

  5. で使用しているエイリアス
    SELECT

    句、適切な列名を使って

    postmeta.meta_value

    項目を提示します。ここでは、

    color.meta_value AS color

    .

それをそうのような別の属性の多くを得る

LEFT JOIN

操作のカスケードを積み重ねることができますこのパターンを使用するのに慣れる

     SELECT wp_posts.ID, wp_posts.post_title, wp_posts.whatever,
            color.meta_value        AS color,
            transmission.meta_value AS transmission,
            model.meta_value        AS model,
            brand.meta_value        AS brand
       FROM wp_posts

  LEFT JOIN wp_postmeta  AS color 
         ON wp_posts.ID = color.post_id        AND color.meta_key='color'

  LEFT JOIN wp_postmeta  AS transmission
         ON wp_posts.ID = transmission.post_id AND transmission.meta_key='transmission'

  LEFT JOIN wp_postmeta  AS model
         ON wp_posts.ID = model.post_id        AND model.meta_key='model'

  LEFT JOIN wp_postmeta  AS  brand
         ON wp_posts.ID = brand.post_id        AND brand.meta_key='brand'

      WHERE wp_posts.post_status = 'publish'
        AND wp_posts.post_type = 'car'
   ORDER BY wp_posts.post_title

このクエリを容易にパターンを表示するインデントの束をやった。さまざまなインデント スタイルを好むことがあります

にくいなぜあなたの質問に、クエリでパフォーマンスの問題を過ごしていた知っています。それは多分し、フィルター処理されたすべての

INNER JOIN

操作の組合せ爆発を得ていたのでです。しかし、任意のレートであなたを示したクエリはおそらく行を返すありません

は、パフォーマンスの問題がまだ解決されない場合は

(post_id, meta_key, meta_value)

列に

postmeta

に複合インデックスを作成してみてください。それはおそらくプラグインのインストール時に行うには仕事のワードプレスのプラグインを作成する場合

答え

これはワードプレスのデータベースとアプリケーションの他の部分を破ることができるまたは将来的に複雑にアップグレードされたので、スキーマに大きな変更を加えるには消極的かもしれない

このクエリの難しさは 1 つの の設計に欠点を示しています。設計は柔軟で新しい属性を実行時に、作成することができる多くのようなデータに対するクエリを従来テーブルとなるよりも複雑になります

ワードプレスのスキーマも最適化されていない。いくつかの素朴なインデックス付けのミス 4.0 の最新のバージョンでさえがあります

この特定のクエリの次の 2 つのヘルプ インデックス:

CREATE INDEX `bk1` ON wp_postmeta (`post_id`,`meta_key`,`meta_value`(255));

CREATE INDEX `bk2` ON wp_posts (`post_type`,`post_status`,`post_title`(255));

丁度正しい meta キー 値を検索するのに役立ちます

bk1

インデックス

bk2

インデックスは当てはまるの回避に役立ちます

これらのインデックスがので、インデックスはカバーできない

post_title

meta_value

は、

TEXT

列およびこれらは完全にインデックスを作成するのには長すぎます。

VARCHAR(255)

を変更する必要があります。しかし、それは場合それはそのテーブル内の長い文字列を格納するのに応じて、アプリケーションを壊してしまう危険します

+----+-------------+--------------+------------+------+---------------+------+---------+----------------------------+------+----------+-----------------------+
| id | select_type | table        | partitions | type | possible_keys | key  | key_len | ref                        | rows | filtered | Extra                 |
+----+-------------+--------------+------------+------+---------------+------+---------+----------------------------+------+----------+-----------------------+
|  1 | SIMPLE      | wp_posts     | NULL       | ref  | bk2           | bk2  | 124     | const,const                |    1 |   100.00 | Using index condition |
|  1 | SIMPLE      | color        | NULL       | ref  | bk1           | bk1  | 1542    | wp.wp_posts.ID,const,const |    1 |   100.00 | Using index           |
|  1 | SIMPLE      | transmission | NULL       | ref  | bk1           | bk1  | 1542    | wp.wp_posts.ID,const,const |    1 |   100.00 | Using index           |
|  1 | SIMPLE      | model        | NULL       | ref  | bk1           | bk1  | 1542    | wp.wp_posts.ID,const,const |    1 |   100.00 | Using index           |
|  1 | SIMPLE      | brand        | NULL       | ref  | bk1           | bk1  | 1542    | wp.wp_posts.ID,const,const |    1 |   100.00 | Using index           |
+----+-------------+--------------+------------+------+---------------+------+---------+----------------------------+------+----------+-----------------------+

の答え

パフォーマンスしてみてください:

プルする列を明示的に指定します。可能性がありますまたは必要がありますどのようなインデックスを参照してください。引っ張られる行の数を制限します

答え

これは良いですか?

SELECT
            P.*,
            C.`meta_value` color,
            T.`meta_value` transmission,
            M.`meta_value` model,
            B.`meta_value` brand
    FROM
            `wp_posts` P
        JOIN
            `wp_postmeta` C
                ON P.`ID` = C.`post_id` AND C.`meta_key` = 'color'
        JOIN
            `wp_postmeta` T
                ON P.`ID` = T.`post_id` AND T.`meta_key` = 'transmission'
        JOIN
            `wp_postmeta` M
                ON P.`ID` = M.`post_id` AND M.`meta_key` = 'model'
        JOIN
            `wp_postmeta` B
                ON P.`ID` = B.`post_id` AND B.`meta_key` = 'brand'
    WHERE
            C.`meta_value` = 'red'
        AND
            T.`meta_value` = 'auto'
        AND
            M.`meta_value` = 'model'
        AND
            B.`meta_value` = 'brand'
        AND
            P.`post_status` = 'publish'
        AND
            P.`post_type` = 'car'
    ORDER BY
            P.`post_title`

が、そのまだ遅い場合ことになるだろう、このインデックスを追加してみてください

CREATE INDEX `IX-wp_postmeta-post_id-meta_key-meta_value`
    ON `wp_postmeta` (`post_id`, `meta_key`, `meta_value`);

もこのインデックスを

wp_post

に追加することを試みることができる

CREATE UNIQUE INDEX `IX-wp_post-post_status-post_type-post_title-ID`
    ON `wp_post` (`post_stauts`, `post_type`, `post_title`, `ID`);

選択のリストを制限するより多く (

SELECT

間のビットと

FROM

、) より良い。多くの使用しないデータを返すにはポイントはありません。全体選択リストは、「カバー」インデックス場合、最適なパフォーマンスが得られます

答え

実際に結果を処理するコードを変更することができますと仮定すると、私は、多くの単純なクエリを作成し、結果をフィルター処理するコードを使用します

SELECT [wp_posts fields you care about], wp_postmeta.meta_key, wp_postmeta.meta_value
FROM wp_posts
INNER JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id 
WHERE wp_posts.post_status = 'publish' AND wp_posts.post_type = 'car'
   AND wp_postmeta.meta_key IN ('color', 'transmission', 'model', 'brand')
ORDER BY wp_posts.post_title, wp_postmeta.meta_key, wp_postmeta.meta_value;

または何かのような.

SELECT [wp_posts fields desired], COUNT(*) AS matchCount
FROM wp_posts INNER JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id
WHERE wp_posts.post_status = 'publish' AND wp_posts.post_type = 'car'
    AND ((meta_key = 'color' AND meta_value = 'red')
        OR (meta_key = 'transmission' AND meta_value = 'auto')
        OR [etc...]
        )
GROUP BY wp_posts.ID
HAVING matchCount = [number of key-value pairs you're checking]
;

の答え

のワードプレスは、良好なクエリ ツールです、WP_Query。記事を検索するメタ値をこのコードを使用することができます:

$args = array(
    'post_type'  => 'post',
    'meta_query' => array(
            array(
                'key'     => 'fieldname',
                'value'   => 'fieldvalue',
                'compare' => 'LIKE',
            ),
        ),
    );
    $query = new WP_Query( $args );
    if ( $query->have_posts() ) {
        while ( $query->have_posts() ) {
            $query->the_post();
            $custom = get_post_custom();

            print_r($post);
            print_r($custom);
        }
    } else {
        // no posts found
    }
    wp_reset_postdata();

クエリ API の詳細については、このサイトを参照してください、多くの例がある: http://codex.wordpress.org/Class_Reference/WP_Query

http://stackoverflow.com/questions/28515894/create-temp-table-from-wp-postsmeta

スポンサーリンク

Leave a Reply