如何优化我的查询?使用类别和标签列表导出 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 中,正确地制作具有多个类别、多个标签和搜索的查询集?

pb中 如何把两个表中的内容导出到一个电子表格 如何把一个字段作为下拉列表框的item

优化查询(LEFT JOIN)

oracle怎么把查询的结果导出word或excle

java freemarker 通过ftl模板导出word文档