web-dev-qa-db-ja.com

非常に遅いクエリを改善または最適化する

私はかなり大きなデータベースを持っています - wp_postsに113,299行、wp_postmetaに216,0649行です。

投稿が追加または編集された後に実行するカスタムクエリが1つあります。これは、実行するたびにMySQLのスローログファイルに表示されます。

これはquery_postsでそれがどのように見えるかです:

    $args = array( 
                'meta_query' => array(
                                    array(
                                        'key' => 'article_template',
                                        'value' => 'news',
                                    ),
                                ),
                'posts_per_page' => '30',
                'category__in' => array( 3, 4, 5 ),
                'post_status' => 'publish',
                'no_found_rows' => true,
                'orderby' => 'meta_value',
                'meta_key' => 'article_datetime',
                'order' => 'DESC'
            );
    query_posts( $args );

そしてこれはMySQLのスローログファイルではこんな感じです:

SELECT   wp_posts.ID FROM wp_posts  INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id) WHERE 1=1  AND ( wp_term_relationships.term_taxonomy_id IN (3,4,5) ) AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish') AND (wp_postmeta.meta_key = 'article_datetime'
AND  (mt1.meta_key = 'article_template' AND CAST(mt1.meta_value AS CHAR) = 'news') ) GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value DESC LIMIT 0, 30;

これはEXPLAINがこのクエリに対して示すものです。

mysql> explain SELECT   wp_posts.ID FROM wp_posts  INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
    -> INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id) WHERE 1=1  AND ( wp_term_relationships.term_taxonomy_id IN (3,4,5) ) AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish') AND (wp_postmeta.meta_key = 'article_datetime' AND  (mt1.meta_key = 'article_template' AND CAST(mt1.meta_value AS CHAR) = 'news') ) GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value DESC LIMIT 0, 30;
+----+-------------+-----------------------+--------+--------------------------+----------+---------+-----------------------------+-------+----------------------------------------------+
| id | select_type | table                 | type   | possible_keys            | key      | key_len | ref                         | rows  | Extra                                        |
+----+-------------+-----------------------+--------+--------------------------+----------+---------+-----------------------------+-------+----------------------------------------------+
|  1 | SIMPLE      | wp_postmeta           | ref    | post_id,meta_key         | meta_key | 768     | const                       | 98576 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | wp_posts              | eq_ref | PRIMARY,type_status_date | PRIMARY  | 8       | toi_web.wp_postmeta.post_id |     1 | Using where                                  |
|  1 | SIMPLE      | mt1                   | ref    | post_id,meta_key         | post_id  | 8       | toi_web.wp_postmeta.post_id |    11 | Using where                                  |
|  1 | SIMPLE      | wp_term_relationships | ref    | PRIMARY,term_taxonomy_id | PRIMARY  | 8       | toi_web.mt1.post_id         |     2 | Using where; Using index                     |
+----+-------------+-----------------------+--------+--------------------------+----------+---------+-----------------------------+-------+----------------------------------------------+

だから、誰かがこれを最適化して遅い問い合わせを避けるための良いヒントや提案があるのではないかと思いますか?これを別のquery_postsループに分割しますか?それとも、簡単なwpdb->get_resultsクエリで投稿のIDをつかむ?

私はどんな提案にもオープンです:)

ところで、私たちは非常に堅牢なMySQLクラスタを持っているので、サーバリソースは問題ではありません

3
Biranit Goren
  1. "article_datetime"を数値と仮定して、 'orderby' => 'meta_value'を使う代わりに 'orderby' => 'meta_value_num'を使うことをお勧めします
  2. それでもクエリが遅い場合は、削除してください。

    'orderby' => 'meta_value'、 'meta_key' => 'article_datetime'、 'order' => 'DESC'

代わりにphpで結果をソートしてください。

2
Fiaz Husyn