如何改进 WordPress insert/update 查询?
How to improve WordPress insert/update query?
我正在创建我自己的 Wordpress 插件,它将配置文件导入为 posts,并且在脚本工作的同时,我希望改进 inserts/updates 和 posts 的查询。
此脚本每 5 分钟运行一次,工作方式如下,
1.import/update 来自本地 users table 的外部来源的所有配置文件。这很简单并且工作正常
2。在更新
之前将所有现有 posts 自定义字段 status 设置为离线
$offline = "UPDATE $meta SET meta_value='offline' WHERE meta_key='status'";
3。 Select 来自 table 用户 所有在线个人资料
$new_query = "SELECT * FROM users WHERE status='online' ORDER BY visitors DESC";
4。对于每个配置文件,如果 post 存在,则更新,否则创建新的 post
$result = $wpdb->get_results($new_query);
foreach ($result as $post){
$cat = $post->gender.'s';
$getterm = get_term_by('name',$cat,'user-category');
$cat_id = $getterm->term_id;
$custfields = array (
'name' => $post->name,
'age' => $post->age,
'subject' => $post->subject,
'status' => $post->status,
'fans' => $post->fans,
'visitors' => $post->visitors,
);
endif;
$postarr = array (
'post_title' => $post->username,
'post_name' => $post->username.'-profile',
'post_content' => 'something',
'post_type' => 'users-profile',
'post_category' => array($cat_id),
'post_status' => 'publish',
'meta_input' => $custfields
);
$postcheck = get_page_by_title($post->username,OBJECT, 'users-profile');
if($postcheck):
update_post_meta($postcheck->ID ,'subject', $post->subject );
update_post_meta($postcheck->ID ,'status', $post->status );
update_post_meta($postcheck->ID ,'visitors', $post->visitors );
else :
wp_set_object_terms(wp_insert_post( $postarr,true),$cat_id,'user-category',true);
endif;
}
SHOW CREATE TABLE wp_users
wp_users CREATE TABLE `wp_users` (
`username` varchar(111) COLLATE utf8mb4_unicode_520_ci NOT NULL,
`name` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
`age` int(11) NOT NULL,
`gender` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
`subject` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
`languages` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
`isnew` tinyint(1) NOT NULL,
`imagebig` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
`fans` int(11) NOT NULL,
`visitors` int(11) NOT NULL,
`timeonline` int(11) NOT NULL,
`status` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
`location` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci
SHOW CREATE TABLE `wp_postmeta`
wp_postmeta CREATE TABLE `wp_postmeta` (
`meta_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_id` bigint(20) unsigned NOT NULL DEFAULT 0,
`meta_key` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meta_value` longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`meta_id`),
KEY `post_id` (`post_id`),
KEY `meta_key` (`meta_key`(191))
) ENGINE=InnoDB AUTO_INCREMENT=405678 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SHOW CREATE TABLE `wp_posts`
wp_posts 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 COLLATE utf8mb4_unicode_ci NOT NULL,
`post_title` text COLLATE utf8mb4_unicode_ci NOT NULL,
`post_excerpt` text COLLATE utf8mb4_unicode_ci NOT NULL,
`post_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'publish',
`comment_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'open',
`ping_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'open',
`post_password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`post_name` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`to_ping` text COLLATE utf8mb4_unicode_ci NOT NULL,
`pinged` text COLLATE utf8mb4_unicode_ci 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 COLLATE utf8mb4_unicode_ci NOT NULL,
`post_parent` bigint(20) unsigned NOT NULL DEFAULT 0,
`guid` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`menu_order` int(11) NOT NULL DEFAULT 0,
`post_type` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'post',
`post_mime_type` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`comment_count` bigint(20) NOT NULL DEFAULT 0,
PRIMARY KEY (`ID`),
KEY `post_name` (`post_name`(191)),
KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
KEY `post_parent` (`post_parent`),
KEY `post_author` (`post_author`)
) ENGINE=InnoDB AUTO_INCREMENT=57991 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
我想做的是,在 update/insert 之后移动离线开关,并将其应用于所有 post 不在 SELECT 语句中...也许update/insert 的更好方法。
也许是这样的:
Select 来自用户 table、select post 的与配置文件匹配的所有在线配置文件(post 标题 = 个人资料用户名),如果 post exist update else create,将 table 中剩余的 post 切换为离线。这可能吗?
谢谢
前缀索引 (KEY meta_key
(meta_key
(191))) 是可憎的。是的,由于 utf8mb4
,这是一个 'necessary' 的拼凑。但它正在伤害你。这样做
SELECT MAX(CHAR_LENGTH(meta_key)) from wp_postmeta;
如果返回 191 或更少,则将 meta_key 的大小更改为 191 并删除索引中的 (191)
。并查看 http://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta
中的其他提示
这些提示可能是您问题的解决方案。
UPDATEing
很多行中的标志似乎是一种笨拙的处理方式。有没有一种方法可以在不使用 offline/online 标志的情况下简单地折叠新数据? (我想我仍然缺少意图。)如果是一百万行,则更新可能需要很长时间。
"all posts not in the SELECT" -- 这听起来像是 "multi-table UPDATE" 语句。它将涉及 LEFT JOIN ON ... WHERE ... IS NULL
。你能用重要的列模拟几行吗?向我们展示这些表格中应该包含的 "before" 和 "after"。
您也可以将上述操作应用于 post_name
。
age
int(11)
你 运行 每年都会增加吗?
我正在创建我自己的 Wordpress 插件,它将配置文件导入为 posts,并且在脚本工作的同时,我希望改进 inserts/updates 和 posts 的查询。
此脚本每 5 分钟运行一次,工作方式如下,
1.import/update 来自本地 users table 的外部来源的所有配置文件。这很简单并且工作正常
2。在更新
之前将所有现有 posts 自定义字段 status 设置为离线$offline = "UPDATE $meta SET meta_value='offline' WHERE meta_key='status'";
3。 Select 来自 table 用户 所有在线个人资料
$new_query = "SELECT * FROM users WHERE status='online' ORDER BY visitors DESC";
4。对于每个配置文件,如果 post 存在,则更新,否则创建新的 post
$result = $wpdb->get_results($new_query);
foreach ($result as $post){
$cat = $post->gender.'s';
$getterm = get_term_by('name',$cat,'user-category');
$cat_id = $getterm->term_id;
$custfields = array (
'name' => $post->name,
'age' => $post->age,
'subject' => $post->subject,
'status' => $post->status,
'fans' => $post->fans,
'visitors' => $post->visitors,
);
endif;
$postarr = array (
'post_title' => $post->username,
'post_name' => $post->username.'-profile',
'post_content' => 'something',
'post_type' => 'users-profile',
'post_category' => array($cat_id),
'post_status' => 'publish',
'meta_input' => $custfields
);
$postcheck = get_page_by_title($post->username,OBJECT, 'users-profile');
if($postcheck):
update_post_meta($postcheck->ID ,'subject', $post->subject );
update_post_meta($postcheck->ID ,'status', $post->status );
update_post_meta($postcheck->ID ,'visitors', $post->visitors );
else :
wp_set_object_terms(wp_insert_post( $postarr,true),$cat_id,'user-category',true);
endif;
}
SHOW CREATE TABLE wp_users
wp_users CREATE TABLE `wp_users` (
`username` varchar(111) COLLATE utf8mb4_unicode_520_ci NOT NULL,
`name` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
`age` int(11) NOT NULL,
`gender` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
`subject` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
`languages` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
`isnew` tinyint(1) NOT NULL,
`imagebig` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
`fans` int(11) NOT NULL,
`visitors` int(11) NOT NULL,
`timeonline` int(11) NOT NULL,
`status` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
`location` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci
SHOW CREATE TABLE `wp_postmeta`
wp_postmeta CREATE TABLE `wp_postmeta` (
`meta_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_id` bigint(20) unsigned NOT NULL DEFAULT 0,
`meta_key` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meta_value` longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`meta_id`),
KEY `post_id` (`post_id`),
KEY `meta_key` (`meta_key`(191))
) ENGINE=InnoDB AUTO_INCREMENT=405678 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SHOW CREATE TABLE `wp_posts`
wp_posts 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 COLLATE utf8mb4_unicode_ci NOT NULL,
`post_title` text COLLATE utf8mb4_unicode_ci NOT NULL,
`post_excerpt` text COLLATE utf8mb4_unicode_ci NOT NULL,
`post_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'publish',
`comment_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'open',
`ping_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'open',
`post_password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`post_name` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`to_ping` text COLLATE utf8mb4_unicode_ci NOT NULL,
`pinged` text COLLATE utf8mb4_unicode_ci 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 COLLATE utf8mb4_unicode_ci NOT NULL,
`post_parent` bigint(20) unsigned NOT NULL DEFAULT 0,
`guid` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`menu_order` int(11) NOT NULL DEFAULT 0,
`post_type` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'post',
`post_mime_type` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`comment_count` bigint(20) NOT NULL DEFAULT 0,
PRIMARY KEY (`ID`),
KEY `post_name` (`post_name`(191)),
KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
KEY `post_parent` (`post_parent`),
KEY `post_author` (`post_author`)
) ENGINE=InnoDB AUTO_INCREMENT=57991 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
我想做的是,在 update/insert 之后移动离线开关,并将其应用于所有 post 不在 SELECT 语句中...也许update/insert 的更好方法。
也许是这样的:
Select 来自用户 table、select post 的与配置文件匹配的所有在线配置文件(post 标题 = 个人资料用户名),如果 post exist update else create,将 table 中剩余的 post 切换为离线。这可能吗?
谢谢
前缀索引 (KEY meta_key
(meta_key
(191))) 是可憎的。是的,由于 utf8mb4
,这是一个 'necessary' 的拼凑。但它正在伤害你。这样做
SELECT MAX(CHAR_LENGTH(meta_key)) from wp_postmeta;
如果返回 191 或更少,则将 meta_key 的大小更改为 191 并删除索引中的 (191)
。并查看 http://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta
这些提示可能是您问题的解决方案。
UPDATEing
很多行中的标志似乎是一种笨拙的处理方式。有没有一种方法可以在不使用 offline/online 标志的情况下简单地折叠新数据? (我想我仍然缺少意图。)如果是一百万行,则更新可能需要很长时间。
"all posts not in the SELECT" -- 这听起来像是 "multi-table UPDATE" 语句。它将涉及 LEFT JOIN ON ... WHERE ... IS NULL
。你能用重要的列模拟几行吗?向我们展示这些表格中应该包含的 "before" 和 "after"。
您也可以将上述操作应用于 post_name
。
age
int(11)
你 运行 每年都会增加吗?