• Resolved lkraav

    (@lkraav)


    Hi. Thanks for all your work here, looks promising.

    Before I half-blind start modding my production database, I thought I’d get in touch for some additional insight.

    I ran pt-query-digest on our slowlog, and while there’s much to work, let’s try to get the top dog:

    # Query 1: 0.00 QPS, 0.04x concurrency, ID 0x28AB87B871626673FCB0584780489FAC at byte 225925344
    # This item is included in the report because it matches --limit.
    # Scores: V/M = 4.68
    # Time range: 2018-07-05 11:05:20 to 2021-11-29 06:41:08
    # Attribute    pct   total     min     max     avg     95%  stddev  median
    # ============ === ======= ======= ======= ======= ======= ======= =======
    # Count         47  162236
    # Exec time     39 3843531s     10s    468s     24s     40s     11s     21s
    # Lock time      2      8s    34us     6ms    51us    63us    50us    44us
    # Rows sent      0 312.21k       0     212    1.97    7.70    5.68    0.99
    # Rows examine  34 405.46G 603.47k   3.49M   2.56M   3.34M 487.83k   2.26M
    # Query size    42  58.67M     373     383  379.19  381.65       5  363.48
    # String:
    # Databases    wp
    # Hosts        localhost
    # Users        wp
    # Query_time distribution
    #   1us
    #  10us
    # 100us
    #   1ms
    #  10ms
    # 100ms
    #    1s
    #  10s+  ################################################################
    # Tables
    #    SHOW TABLE STATUS FROM <code>wp</code> LIKE 'wp_posts'\G
    #    SHOW CREATE TABLE <code>wp</code>.<code>wp_posts</code>\G
    #    SHOW TABLE STATUS FROM <code>wp</code> LIKE 'wp_postmeta'\G
    #    SHOW CREATE TABLE <code>wp</code>.<code>wp_postmeta</code>\G
    # EXPLAIN /*!50100 PARTITIONS*/
    SELECT posts.ID
                                    FROM wp_posts AS posts
                                    LEFT JOIN wp_postmeta AS meta on posts.ID = meta.post_id
                                    WHERE meta.meta_key = '_customer_user'
                                    AND   meta.meta_value = '3595'
                                    AND   posts.post_type = 'shop_order'
                                    AND   posts.post_status IN ( 'wc-pending','wc-processing','wc-on-hold','wc-completed','wc-cancelled','wc-refunded','wc-failed' )
                                    ORDER BY posts.ID DESC

    EXPLAIN says we definitely don’t have the necessary indexes in place thus far

    MariaDB [wp]> EXPLAIN SELECT posts.ID                                 FROM wp_posts AS posts                                 LEFT JOIN wp_postmeta AS meta on posts.ID = meta.post_id                                 WHERE meta.meta_key = '_customer_user'                                 AND   meta.meta_value = '32493'                                 AND   posts.post_type = 'shop_order'                                 AND   posts.post_status IN ( 'wc-pending','wc-processing','wc-on-hold','wc-completed','wc-cancelled','wc-refunded','wc-failed' )                                 ORDER BY posts.ID DESC;
    +------+-------------+-------+-------+----------------------------+------------------+---------+----------------------------+--------+------------------------------------------+
    | id   | select_type | table | type  | possible_keys              | key              | key_len | ref                        | rows   | Extra                                    |
    +------+-------------+-------+-------+----------------------------+------------------+---------+----------------------------+--------+------------------------------------------+
    |    1 | SIMPLE      | posts | range | PRIMARY,type_status_date   | type_status_date | 164     | NULL                       | 108897 | Using where; Using index; Using filesort |
    |    1 | SIMPLE      | meta  | ref   | post_id,meta_key,post_id_2 | post_id          | 8       | wp.posts.ID |      1 | Using where                              |
    +------+-------------+-------+-------+----------------------------+------------------+---------+----------------------------+--------+------------------------------------------+
    2 rows in set (0.002 sec)

    Index states

    MariaDB [wp]> SHOW INDEX FROM wp_postmeta;
    +-------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    | Table       | Non_unique | Key_name  | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
    +-------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    | wp_postmeta |          0 | PRIMARY   |            1 | meta_id     | A         |     4943116 |     NULL | NULL   |      | BTREE      |         |               |
    | wp_postmeta |          1 | post_id   |            1 | post_id     | A         |     4943116 |     NULL | NULL   |      | BTREE      |         |               |
    | wp_postmeta |          1 | meta_key  |            1 | meta_key    | A         |       17344 |      191 | NULL   | YES  | BTREE      |         |               |
    | wp_postmeta |          1 | post_id_2 |            1 | post_id     | A         |     4943116 |     NULL | NULL   |      | BTREE      |         |               |
    | wp_postmeta |          1 | post_id_2 |            2 | meta_key    | A         |     4943116 |     NULL | NULL   | YES  | BTREE      |         |               |
    +-------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    5 rows in set (0.000 sec)
    
    MariaDB [wp]> SHOW INDEX FROM wp_posts;
    +----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    | Table    | Non_unique | Key_name         | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
    +----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    | wp_posts |          0 | PRIMARY          |            1 | ID           | A         |     4250786 |     NULL | NULL   |      | BTREE      |         |               |
    | wp_posts |          1 | type_status_date |            1 | post_type    | A         |         118 |     NULL | NULL   |      | BTREE      |         |               |
    | wp_posts |          1 | type_status_date |            2 | post_status  | A         |         274 |     NULL | NULL   |      | BTREE      |         |               |
    | wp_posts |          1 | type_status_date |            3 | post_date    | A         |     4250786 |     NULL | NULL   |      | BTREE      |         |               |
    | wp_posts |          1 | type_status_date |            4 | ID           | A         |     4250786 |     NULL | NULL   |      | BTREE      |         |               |
    | wp_posts |          1 | post_parent      |            1 | post_parent  | A         |       41674 |     NULL | NULL   |      | BTREE      |         |               |
    | wp_posts |          1 | post_author      |            1 | post_author  | A         |       51214 |     NULL | NULL   |      | BTREE      |         |               |
    | wp_posts |          1 | post_name        |            1 | post_name    | A         |     4250786 |      191 | NULL   |      | BTREE      |         |               |
    | wp_posts |          1 | bsearch_title    |            1 | post_title   | NULL      |        NULL |     NULL | NULL   |      | FULLTEXT   |         |               |
    | wp_posts |          1 | bsearch_content  |            1 | post_content | NULL      |        NULL |     NULL | NULL   |      | FULLTEXT   |         |               |
    +----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    10 rows in set (0.000 sec)

    What are your thoughts on how to index for this? Does one of the plugin’s built-in strategies apply to this already, or need to think custom?

    Willing to to pay for consultation time, let me know about options, thank you.

    • This topic was modified 2 years, 8 months ago by lkraav.
    • This topic was modified 2 years, 8 months ago by lkraav.
    • This topic was modified 2 years, 8 months ago by lkraav.
    • This topic was modified 2 years, 8 months ago by lkraav.
Viewing 4 replies - 1 through 4 (of 4 total)
  • Plugin Author OllieJones

    (@olliejones)

    The plugin is built to help with WooCommerce queries like the one you mention. It’s worth your trouble to try optimizing your wp_postmeta table with the plugin. I suggest you use the wp-cli command wp index-mysql enable wp_postmeta to do that, to avoid timeouts.

    If you need more speedup than the current version of the plugin offers, take a look at this support-forum post for an additional tweak to the key. https://wordpress.org/support/topic/wp_postmeta-terribly-slow/#post-15093254

    Your wp_posts table has two nonstandard fulltext keys, so you may not be able to use the plugin to add keys to it. But that doesn’t matter because one of the standard keys is the right key to use for that.

    Thread Starter lkraav

    (@lkraav)

    > I suggest you use the wp-cli command wp index-mysql enable wp_postmeta to do that, to avoid timeouts.

    Thanks. I’m unclear about whether modifying indexes does or does not lock up a production database?

    I just recently did run an ADD INDEX operation, and site seemed to have kept running for the 180 seconds time it took.

    It seems my wp_postmeta has ~5M rows, should be indexed in a few minutes I think.

    [~/www]# wp index-mysql tables
    Index WP MySQL For Speed 1.3.3
    Versions MySQL:10.3.27-MariaDB-log WordPress:5.8.2 php:7.4.18
    Notice: Undefined index: format in /home/www/public_html/wp-content/plugins/index-wp-mysql-for-speed/code/cli.php on line 326
    +----------+--------+---------+-------------+--------------+----------------+--------+------------+--------------------+
    | table    | prefix | count   | distinct_id | distinct_key | autoload_count | engine | row_format | collation          |
    +----------+--------+---------+-------------+--------------+----------------+--------+------------+--------------------+
    | comments | wp_    | 856252  | 65865       |              |                | InnoDB | Dynamic    | utf8mb4_unicode_ci |
    | options  | wp_    | 3706    |             |              | 2450           | InnoDB | Compact    | utf8mb4_unicode_ci |
    | postmeta | wp_    | 4942770 |             | 17343        |                | InnoDB | Dynamic    | utf8mb4_unicode_ci |
    | posts    | wp_    | 4250664 |             |              |                | InnoDB | Dynamic    | utf8mb4_unicode_ci |
    | termmeta | wp_    | 1978    |             | 22           |                | InnoDB | Dynamic    | utf8mb4_unicode_ci |
    | usermeta | wp_    | 1944811 | 54022       | 22354        |                | InnoDB | Dynamic    | utf8mb4_unicode_ci |
    | users    | wp_    | 25171   |             |              |                | InnoDB | Dynamic    | utf8mb4_unicode_ci |
    +----------+--------+---------+-------------+--------------+----------------+--------+------------+--------------------+

    EDIT seems to be doable online https://stackoverflow.com/questions/64794302/create-index-in-huge-mariadb-production-database-without-table-locking

    • This reply was modified 2 years, 8 months ago by lkraav.
    Thread Starter lkraav

    (@lkraav)

    > Thanks. I’m unclear about whether modifying indexes does or does not lock up a production database?

    Answer: it does not.

    10M postmeta index did take 5 minutes to add.

    Plugin Author OllieJones

    (@olliejones)

    It depends on the version of MariaDB / MySQL whether the table is locked during a reindexing. Later versions do it online.

    I’m happy to hear a five-minute reindexing job completed successfully. Thank you for following up.

Viewing 4 replies - 1 through 4 (of 4 total)
  • The topic ‘Optimize for WooCommerce: heavy shop_order post query ideas?’ is closed to new replies.