如何优化我的查询?使用类别和标签列表导出 Wordpress 帖子
Posted
技术标签:
【中文标题】如何优化我的查询?使用类别和标签列表导出 Wordpress 帖子【英文标题】:How to optimize my query? Exporting Wordpress posts with category and tag list 【发布时间】:2013-01-09 15:06:00 【问题描述】:我为导出帖子写了查询。
SELECT
post_name,
post_content,
Categories,
Tags
FROM
-- posts
wp_posts as p
-- categories
LEFT JOIN
(SELECT
object_id as cat_obj_id,
GROUP_CONCAT(cat_term.name) as Categories
FROM
wp_term_relationships AS cat_r
JOIN wp_term_taxonomy AS cat_tax
ON cat_r.term_taxonomy_id = cat_tax.term_taxonomy_id
JOIN wp_terms AS cat_term
ON cat_tax.term_id = cat_term.term_id
WHERE cat_tax.taxonomy="category"
GROUP by object_id)
as c
ON p.id = c.cat_obj_id
-- tags
LEFT JOIN
(SELECT
object_id as tag_obj_id,
GROUP_CONCAT(tag_term.name) as Tags
FROM
wp_term_relationships AS tag_r
JOIN wp_term_taxonomy AS tag_tax
ON tag_r.term_taxonomy_id = tag_tax.term_taxonomy_id
JOIN wp_terms AS tag_term
ON tag_tax.term_id = tag_term.term_id
WHERE tag_tax.taxonomy="post_tag"
GROUP by object_id)
as t
ON p.id = t.tag_obj_id
表架构:
CREATE TABLE `wp_term_taxonomy` (
`term_taxonomy_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`term_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`taxonomy` varchar(32) NOT NULL DEFAULT '',
`description` longtext NOT NULL,
`parent` bigint(20) unsigned NOT NULL DEFAULT '0',
`count` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`term_taxonomy_id`),
UNIQUE KEY `term_id_taxonomy` (`term_id`,`taxonomy`),
KEY `taxonomy` (`taxonomy`)
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8$$
CREATE TABLE `wp_term_relationships` (
`object_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`term_taxonomy_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`term_order` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`object_id`,`term_taxonomy_id`),
KEY `term_taxonomy_id` (`term_taxonomy_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8$$
CREATE TABLE `wp_terms` (
`term_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(200) NOT NULL DEFAULT '',
`slug` varchar(200) NOT NULL DEFAULT '',
`term_group` bigint(10) NOT NULL DEFAULT '0',
PRIMARY KEY (`term_id`),
UNIQUE KEY `slug` (`slug`),
KEY `name` (`name`)
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8$$
CREATE TABLE `wp_posts` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_author` bigint(20) unsigned NOT NULL DEFAULT '0',
`post_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`post_date_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`post_content` longtext NOT NULL,
`post_title` text NOT NULL,
`post_excerpt` text NOT NULL,
`post_status` varchar(20) NOT NULL DEFAULT 'publish',
`comment_status` varchar(20) NOT NULL DEFAULT 'open',
`ping_status` varchar(20) NOT NULL DEFAULT 'open',
`post_password` varchar(20) NOT NULL DEFAULT '',
`post_name` varchar(200) NOT NULL DEFAULT '',
`to_ping` text NOT NULL,
`pinged` text NOT NULL,
`post_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`post_modified_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`post_content_filtered` longtext NOT NULL,
`post_parent` bigint(20) unsigned NOT NULL DEFAULT '0',
`guid` varchar(255) NOT NULL DEFAULT '',
`menu_order` int(11) NOT NULL DEFAULT '0',
`post_type` varchar(20) NOT NULL DEFAULT 'post',
`post_mime_type` varchar(100) NOT NULL DEFAULT '',
`comment_count` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `post_name` (`post_name`),
KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
KEY `post_parent` (`post_parent`),
KEY `post_author` (`post_author`)
) ENGINE=MyISAM AUTO_INCREMENT=9082 DEFAULT CHARSET=utf8$$
解释:
在 1000 个帖子数据库上运行此查询需要 72 秒(在 1 秒内执行,提取需要永远)。有什么方法可以让它更快,没有临时表来存储类别和标签?
【问题讨论】:
您需要向我们展示表和索引定义。 诊断慢查询需要完整的表和索引定义,而不仅仅是描述或解释。也许您的表格定义不佳。也许索引没有正确创建。也许您认为您在该列上没有索引。没有看到表和索引定义,我们无法判断。 这些表有没有被索引?您没有显示任何索引定义。 所有连接和taxonomy
字段都有索引,在子查询的WHERE
子句中。
【参考方案1】:
我发现,当子查询之一(LEFT JOIN
'ed)上没有记录时,我的大查询运行速度非常慢。
为了解决这个问题 - 我从子查询创建了临时表,并用这些临时表替换了子查询。
这是我的 SQL。
-- 1.1. Creating table for post categories
create table if not exists temp_categories
(
ID bigint not null AUTO_INCREMENT,
Categories text not null,
PRIMARY KEY (ID)
) DEFAULT CHARSET=utf8;
-- 1.2. Filling table temp_categories
INSERT INTO temp_categories(ID, Categories)
SELECT
'object_id' AS ID, -- post ID
GROUP_CONCAT(cat_term.name ORDER BY cat_term.name) AS Categories -- comma separated category list
FROM
wp_term_relationships AS cat_r
JOIN wp_term_taxonomy AS cat_tax
ON cat_r.term_taxonomy_id = cat_tax.term_taxonomy_id
JOIN wp_terms AS cat_term
ON cat_tax.term_id = cat_term.term_id
WHERE cat_tax.taxonomy="category"
GROUP by object_id;
-- 2.1. Creating table for post tags
create table temp_tags
(
ID bigint not null AUTO_INCREMENT,
Tags text not null,
PRIMARY KEY (ID)
) DEFAULT CHARSET=utf8 ;
-- 2.2. Filling table temp_tags
INSERT INTO exp_tagi(ID, Tagi)
SELECT
object_id AS ID, --post ID
GROUP_CONCAT(tag_term.name ORDER BY tag_term.name) AS Tags -- comma separated tag list
FROM
wp_term_relationships AS tag_r
JOIN wp_term_taxonomy AS tag_tax
ON tag_r.term_taxonomy_id = tag_tax.term_taxonomy_id
JOIN wp_terms AS tag_term
ON tag_tax.term_id = tag_term.term_id
WHERE tag_tax.taxonomy="post_tag"
GROUP by object_id;
-- 3. Exporting posts
SELECT
p.id AS id,
p.post_title AS Title,
p.post_content AS Content,
k.Categories AS Categories,
t.Tags AS Tags,
IF(p.post_status = 'publish', 1, 0) AS Published
FROM
wp_posts p
left join temp_categories k
on p.id = k.id
left join temp_tags t
on p.id = t.id
WHERE post_status in('publish', 'draft')
ORDER BY id;
-- 4. Deleting temporary tables
DROP TABLE temp_categories;
DROP TABLE temp_tags;
我可以使用TEMPORARY
表(不需要删除,它们会在 mysql 会话结束时消失),但我没有,因为我的 php 应用程序在每次查询后都会结束 MySQL 会话。
【讨论】:
以上是关于如何优化我的查询?使用类别和标签列表导出 Wordpress 帖子的主要内容,如果未能解决你的问题,请参考以下文章
在 Django 中,正确地制作具有多个类别、多个标签和搜索的查询集?