面向列的缩放 Mysql - Wordpress

Posted

技术标签:

【中文标题】面向列的缩放 Mysql - Wordpress【英文标题】:Scaling Mysql column oriented - Wordpress 【发布时间】:2016-03-30 03:54:20 【问题描述】:

对于那些不熟悉 WP 的 DBA,它具有面向列的结构(就像许多旨在服务于大多数用例的开源软件一样),随着行数的增加,性能会呈指数级下降。

我知道许多开源 CMS 旨在涵盖大多数不执行的用例。这就是他们使用面向列的数据库设计的原因。

我们用 ElasticSearch 替换了许多查询,但 mysql 仍然是我们的主要数据存储,我想仍然需要一些 SQL 查询来保持数据一致性。

如果我们迁移到我们自己的 Mysql 表结构,我们将失去丰富且广泛使用的 WP API 的所有好处。 (主要是 WP_query() )

明显我们没有做正确的事情,比如简单的查询优化或相对的简单的 DBA 任务,它们可以帮助我们达到 20MM 行而不是数十亿行。

这里有一些慢查询的例子。

EXPLAIN SELECT COUNT(*) FROM wp_posts JOIN (SELECT `post_id` FROM wp_postmeta WHERE `meta_key` = 'et_payment_package' AND `meta_value` IN (246)) as metas ON `ID` = `post_id` WHERE `post_author` = 25492 AND `post_status` = 'publish';



+----+-------------+-------------+--------+---------------------+----------+---------+---------------+--------+-------------+
| id | select_type | table       | type   | possible_keys       | key      | key_len | ref           | rows   | Extra       |
+----+-------------+-------------+--------+---------------------+----------+---------+---------------+--------+-------------+
|  1 | PRIMARY     | <derived2>  | ALL    | NULL                | NULL     | NULL    | NULL          | 110310 |             |
|  1 | PRIMARY     | wp_posts    | eq_ref | PRIMARY,post_author | PRIMARY  | 8       | metas.post_id |      1 | Using where |
|  2 | DERIVED     | wp_postmeta | ref    | meta_key,meta_value | meta_key | 203     |               | 217442 | Using where |
+----+-------------+-------------+--------+---------------------+----------+---------+---------------+--------+-------------+
3 rows in set (5.27 sec)

另一个查询:

Query_time: 23.991255  Lock_time: 0.000174 Rows_sent: 6  Rows_examined: 402008

SELECT wp_users.ID,wp_users.user_login,wp_users.display_name FROM wp_users INNER JOIN wp_usermeta ON ( wp_users.ID = wp_usermeta.user_id ) WHERE 1=1 AND ( ( wp_usermeta.meta_key = 'wp_user_level' AND CAST(wp_usermeta.meta_value AS CHAR) != '0' )) ORDER BY display_name ASC;

+----+-------------+-------------+------+------------------+----------+---------+-----------------------------+--------+----------------+
| id | select_type | table       | type | possible_keys    | key      | key_len | ref                         | rows   | Extra          |
+----+-------------+-------------+------+------------------+----------+---------+-----------------------------+--------+----------------+
|  1 | SIMPLE      | wp_users    | ALL  | PRIMARY          | NULL     | NULL    | NULL                        | 127267 | Using filesort |
|  1 | SIMPLE      | wp_usermeta | ref  | user_id,meta_key | meta_key | 111     | const,tdm_wp_cl.wp_users.ID |      1 | Using where    |
+----+-------------+-------------+------+------------------+----------+---------+-----------------------------+--------+----------------+

@Strawberry 提供的这段代码运行得非常快。任何人都知道这是否可以使用标准的 WP_query API 来完成?

EXPLAIN SELECT COUNT(*) FROM wp_posts p JOIN wp_postmeta m ON p.ID = m.post_id WHERE p.post_author = 25492 AND p.post_status = 'publish'  And m.meta_key = 'et_payment_package' AND m.meta_value IN (246);
+----+-------------+-------+------+-----------------------------+-------------+---------+----------------+------+-------------+
| id | select_type | table | type | possible_keys               | key         | key_len | ref            | rows | Extra       |
+----+-------------+-------+------+-----------------------------+-------------+---------+----------------+------+-------------+
|  1 | SIMPLE      | p     | ref  | PRIMARY,post_author         | post_author | 8       | const          |   12 | Using where |
|  1 | SIMPLE      | m     | ref  | meta_key,post_id,meta_value | post_id     | 8       | tdm_wp_cl.p.ID |    3 | Using where |
+----+-------------+-------+------+-----------------------------+-------------+---------+----------------+------+-------------+
2 rows in set (0.01 sec)

【问题讨论】:

【参考方案1】:

有优化。例如,您的第一个查询中有一个不必要的子查询:

SELECT COUNT(*) 
   FROM wp_posts p
    JOIN wp_postmeta m
    ON p.ID = m.post_id
 WHERE p.post_author = 25492
  AND p.post_status = 'publish' 
 And m.meta_key = 'et_payment_package' 
  AND m.meta_value IN (246) 

同样,我怀疑 CAST 函数禁止使用索引

SELECT u.ID
, u.user_login
, u.display_name 
FROM wp_users u
JOIN wp_usermeta m
 ON u.ID = m.user_id
WHERE m.meta_key = 'wp_user_level' 
AND m.meta_value != 0
ORDER 
 BY display_name ASC;

【讨论】:

谢谢,您的查询速度非常快。您或其他人知道是否可以使用 WP_query API 来完成。 对不起,我是新手,我如何批准答案?

以上是关于面向列的缩放 Mysql - Wordpress的主要内容,如果未能解决你的问题,请参考以下文章

R语言vtreat包自动处理dataframe的缺失值计算数据列的均值和方差并基于均值和方差信息对数据列进行标准化缩放计算所有数据列的均值和方差对所有数据列进行标准化缩放

python数据框特定列的缩放值在1-10之间

面向列的 NoSQL 与面向文档的 NoSQL 有何不同?

比Hive快279倍的数据库-ClickHouse到底是怎样的

查询以查找面向列的表(append_only 表)和分区表的列表

mysql特征缩放计算