我知道,在帖子分组方面,首选使用分类法而非元数据。用简单的话说this和this说的是“使用meta来存储唯一数据,并使用分类法来重复数据(将帖子分组)。”
但是我想知道是否有可能通过引入一种代表该元数据不同范围的分类法来提高元查询性能?
假设我有一家商店,上面放着邮政产品。每个产品都有价格元。我在数据库元表中有数百万行。如果我要添加将在前端过滤器中使用的价格范围分类法,该怎么办?价格范围将类似于“ 1-100 $”,“ 100-1000 $”等。用户单击“ 100-1000 $” +按价格排序。这样,我将查询标记为“ 100-1000 $”的帖子,只有在此之后,它们才会按Price元数据进行排序。会提高查询性能吗?
如果允许用户输入“来自”和“至”价格,该如何实施?使用上面的方法并仅添加价格范围的分类法元可能是一个好主意?看起来像这样:-用户选择“ 90-900 $”-获取所有与该价格范围相匹配的价格范围条款。就是“ 1-100”和“ 100-1000”-查询价格范围(“ 1-100”和“ 100-1000”中的帖子)并将元值“价格”设置为> 90和<900它也会提高性能吗?这种方法需要两个查询:获取条件(按条件元数据过滤),获取帖子。
我没有机会通过一个非常庞大的数据库进行检查,因为我的所有项目都不大。但是我仍然对我的任何方法是否适用于大型网站感兴趣?
编辑(1):我正在附加PHP和SQL
仅通过元查询:
new WP_Query([
'post_type' => 'my_product',
'meta_query' => [
[
'key' => 'price',
'value' => 90,
'compare' => '>=',
'type' => 'NUMERIC'
],
[
'key' => 'price',
'value' => 900,
'compare' => '<=',
'type' => 'NUMERIC'
]
]
]);
EXPLAIN SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
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_postmeta.meta_key = 'price'
AND CAST(wp_postmeta.meta_value AS SIGNED) >= '90' )
AND ( mt1.meta_key = 'price'
AND CAST(mt1.meta_value AS SIGNED) <= '900' )
)
AND wp_posts.post_type = 'my_product'
AND ( wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'acf-disabled'
OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private'
)
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 10
1 SIMPLE wp_postmeta ref post_id,meta_key meta_key 767 const 1 Using where; Using temporary; Using filesort
1 SIMPLE mt1 ref post_id,meta_key meta_key 767 const 1 Using where
1 SIMPLE wp_posts eq_ref PRIMARY,type_status_date,post_author PRIMARY 8 loc.own-acf-plugin.wp_postmeta.post_id 1 Using where
按税金和元数据查询:
new WP_Query([
'post_type' => 'my_product',
'meta_query' => [
[
'key' => 'price',
'value' => 90,
'compare' => '>=',
'type' => 'NUMERIC'
],
[
'key' => 'price',
'value' => 900,
'compare' => '<=',
'type' => 'NUMERIC'
]
],
'tax_query' => [
[
'taxonomy' => 'category',
'field' => 'slug',
'terms' => [ '0-100', '100-1000' ]
]
]
])
EXPLAIN SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
LEFT 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 (1,2) )
AND ( ( wp_postmeta.meta_key = 'price'
AND CAST(wp_postmeta.meta_value AS SIGNED) >= '90' )
AND ( mt1.meta_key = 'price'
AND CAST(mt1.meta_value AS SIGNED) <= '900' )
)
AND wp_posts.post_type = 'my_product'
AND ( wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'acf-disabled'
OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private'
)
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 10
1 SIMPLE wp_term_relationships index PRIMARY,term_taxonomy_id PRIMARY 16
NULL
1 Using where; Using index; Using temporary; Using f...
1 SIMPLE wp_postmeta ref post_id,meta_key meta_key 767 const 1 Using where
1 SIMPLE mt1 ref post_id,meta_key meta_key 767 const 1 Using where
1 SIMPLE wp_posts eq_ref PRIMARY,type_status_date,post_author PRIMARY 8 loc.own-acf-plugin.wp_term_relationships.object_id 1 Using where
以下问题导致性能下降。 (我不知道其中哪些可以在WP中进行改进。)
OR
难以优化JOINs
至wp_postmeta
。可以通过仅将其设为JOIN
并执行一次BETWEEN..AND..
来解决此问题吗?JOIN
可能使其变慢。SQL_CALC_FOUND_ROWS
花费一些。特别是,找到所需的10(LIMIT
)后就无法退出。GROUP BY
和ORDER BY
不同,因此需要额外的排序。将两者都更改为ID
将解决此问题。即使您添加的一个帮助,也不足以抵消其他6个问题。
也许最大的解决办法是在price
中有一个称为wp_posts
的numeric列(并适当地建立了索引)。但这与WP模式哲学完全不同。