我的查询正在减慢我的Wordpress网站的某个区域。我是sql语句的新手,这个特定的语句是由另一个开发人员创建的。有没有办法优化以下声明?我很茫然!我已经包含了执行计划&桌面设计如下,但很乐意提供任何其他信息。我感谢任何帮助。
SELECT DISTINCT wp_posts.ID FROM wp_posts INNER JOIN (
SELECT post_id FROM wp_postmeta
WHERE post_id NOT IN (SELECT post_id FROM wp_postmeta WHERE meta_key = '_wc_restrictions_location')
AND post_id NOT IN(SELECT DISTINCT tr.object_id FROM wp_termmeta
INNER JOIN wp_term_taxonomy tt on wp_termmeta.term_id = tt.term_id
INNER JOIN wp_term_relationships tr on tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy = 'product_cat' AND meta_key='_wc_restrictions_location')
UNION ALL
SELECT post_id FROM wp_postmeta
WHERE (meta_key = '_wc_restrictions_location' AND meta_value = 'public') OR (meta_key = '_wc_restrictions_locations' AND meta_value IN (''))
UNION ALL
SELECT tr.object_id FROM wp_termmeta
INNER JOIN wp_term_taxonomy tt on wp_termmeta.term_id = tt.term_id
INNER JOIN wp_term_relationships tr on tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy = 'product_cat'
AND ( (meta_key='_wc_restrictions_location' AND meta_value='public') OR (meta_key = '_wc_restrictions_locations' AND meta_value IN ('')) )
AND tr.object_id NOT IN (SELECT DISTINCT post_id FROM wp_postmeta WHERE meta_key = '_wc_restrictions_location')
) as rfilter on wp_posts.ID = rfilter.post_id WHERE post_type = 'product' AND ID IN (34913,6926,6928,6929,6931,6932,6933,6934,6935,6936,6937,6938,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,6955,6921,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6970,6971,6973,6974,6976,6977,6979,6981,6984,6985,6986,6987,6988,6989,6990,6992,6993,6995,6996,6997,6999,7000,7001,7003,7005,7006,7008,7009,7010,7011,7012,7013,7014,7015,7016,7017,7018,7019,7020,7021,7023,7024,7025,7061,7062,7064,7065,7066,7068,7069,7070,7071,7072,7073,7074,7075,7076,7077,7078,7079,7080,7083,7084,7085,7087,7089,7090,7091,7092,7093,7094,7095,7096,7098,7099,7100,7101,7102,7103,7105,7106,7107,7108,7109,7111,7112,7113,7116,7128,7129,7130,7131,7136,7137,7338,7451,7633,7117,7348,7399,7400,7489,7540,7631,24265,24576,34966,35025,35092,35209,35287,35344,35371,35400,35414,35468,35490,35543,35598,35706,35718,35757,35838,35890,35944,36001,36039,36093,36117,36171,36183,36192,38458,39593,39667,39693,39703,39777,39783,39789,42683,44209,44693,45536,45972,46360,46749,48415,48553,48703,48715,48861,49619,49766,51010,51792,52182,53167,53171,53189,53197,53211,53230,53470,53472,53476,53478,53480,53485,53487,53489,53492,53500,53503,53505,53508,53511,53514,53517,53520,53522,53526,53529,53532,53539,53542,53544,53546,53549,53552,53555,53557,53560,53563,53566,53569,53571,53586,53613,53622,53626,53630,53633,53636,53640,53643,53647,53650,53653,53657,53660,53664,53670,53673,53676,53679,53707,53722,53739,53743,53746,53749,53774,53779,53791,53794,53797,53801,53804,53868,53887,53892,53897,53900,53908,53913,53918,53923,54279,54282,54286,54289,54292,54295,54312,54340,54347,54352,54435,54438,54441,54444,54471,54476,54594,54609,54612,54616,54619,54622,7135,35314,53494,53617);
描述表结果:
wp_posts CREATE TABLE `wp_posts` (
`ID` bigint(20) unsigned NOT NULL,
`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 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
wp_postmeta CREATE TABLE `wp_postmeta` (
`meta_id` int(11) NOT NULL,
`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,
PRIMARY KEY (`meta_id`),
KEY `post_id` (`post_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
wp_termmeta CREATE TABLE `wp_termmeta` (
`meta_id` bigint(20) unsigned NOT NULL,
`term_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,
PRIMARY KEY (`meta_id`),
KEY `term_id` (`term_id`),
KEY `meta_key` (`meta_key`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
wp_term_taxonomy CREATE TABLE `wp_term_taxonomy` (
`term_taxonomy_id` int(11) NOT NULL,
`term_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`taxonomy` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`description` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
`parent` bigint(20) unsigned NOT NULL DEFAULT '0',
`count` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`term_taxonomy_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
wp_term_relationships 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=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
答案 0 :(得分:2)
我会考虑这两个更改来优化此查询:
让我们从添加索引开始:
ALTER TABLE `wp_postmeta` ADD INDEX `wp_postmeta_index_1` (`meta_key`, `meta_value`, `post_id`);
ALTER TABLE `wp_postmeta` ADD INDEX `wp_postmeta_index_2` (`meta_key`, `post_id`);
ALTER TABLE `wp_posts` ADD INDEX `wp_posts_index_1` (`post_type`, `ID`);
ALTER TABLE `wp_term_relationships` ADD INDEX `wp_term_relationships_index_1` (`term_taxonomy_id`, `object_id`);
ALTER TABLE `wp_term_taxonomy` ADD INDEX `wp_term_taxonomy_index_1` (`taxonomy`, `term_id`, `term_taxonomy_id`);
ALTER TABLE `wp_termmeta` ADD INDEX `wp_termmeta_index_1` (`meta_key`, `meta_value`, `term_id`);
ALTER TABLE `wp_termmeta` ADD INDEX `wp_termmeta_index_2` (`meta_key`, `term_id`);
让我们看一下优化的查询:
SELECT
DISTINCT wp_posts.ID
FROM
wp_posts
INNER JOIN
(
SELECT
wp_postmeta.post_id
FROM
wp_postmeta
WHERE
wp_postmeta.post_id NOT IN (
SELECT
wp_postmeta.post_id
FROM
wp_postmeta
WHERE
wp_postmeta.meta_key = '_wc_restrictions_location'
)
AND wp_postmeta.post_id NOT IN (
SELECT
DISTINCT tr.object_id
FROM
wp_termmeta
INNER JOIN
wp_term_taxonomy tt
ON wp_termmeta.term_id = tt.term_id
INNER JOIN
wp_term_relationships tr
ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE
tt.taxonomy = 'product_cat'
AND wp_termmeta.meta_key = '_wc_restrictions_location'
)
UNION
ALL SELECT
wp_postmeta.post_id
FROM
wp_postmeta
WHERE
(
wp_postmeta.meta_key = '_wc_restrictions_location'
AND wp_postmeta.meta_value = 'public'
)
UNION
ALL SELECT
tr.object_id
FROM
wp_termmeta
INNER JOIN
wp_term_taxonomy tt
ON wp_termmeta.term_id = tt.term_id
INNER JOIN
wp_term_relationships tr
ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE
tt.taxonomy = 'product_cat'
AND (
(
wp_termmeta.meta_key = '_wc_restrictions_location'
AND wp_termmeta.meta_value = 'public'
)
)
AND tr.object_id NOT IN (
SELECT
DISTINCT wp_postmeta.post_id
FROM
wp_postmeta
WHERE
wp_postmeta.meta_key = '_wc_restrictions_location'
)
UNION
DISTINCT SELECT
wp_postmeta.post_id
FROM
wp_postmeta
WHERE
(
wp_postmeta.meta_key = '_wc_restrictions_locations'
AND wp_postmeta.meta_value IN (
''
)
)
UNION
DISTINCT SELECT
tr.object_id
FROM
wp_termmeta
INNER JOIN
wp_term_taxonomy tt
ON wp_termmeta.term_id = tt.term_id
INNER JOIN
wp_term_relationships tr
ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE
tt.taxonomy = 'product_cat'
AND (
(
wp_termmeta.meta_key = '_wc_restrictions_locations'
AND wp_termmeta.meta_value IN (
''
)
)
)
AND tr.object_id NOT IN (
SELECT
DISTINCT wp_postmeta.post_id
FROM
wp_postmeta
WHERE
wp_postmeta.meta_key = '_wc_restrictions_location'
)
) AS rfilter
ON wp_posts.ID = rfilter.post_id
WHERE
wp_posts.post_type = 'product'
AND wp_posts.ID IN (
34913, 6926, 6928, 6929, 6931, 6932, 6933, 6934, 6935, 6936, 6937, 6938, 6942, 6943, 6944, 6945, 6946, 6947, 6948, 6949, 6950, 6951, 6952, 6953, 6954, 6955, 6921, 6956, 6957, 6958, 6959, 6960, 6961, 6962, 6963, 6964, 6965, 6970, 6971, 6973, 6974, 6976, 6977, 6979, 6981, 6984, 6985, 6986, 6987, 6988, 6989, 6990, 6992, 6993, 6995, 6996, 6997, 6999, 7000, 7001, 7003, 7005, 7006, 7008, 7009, 7010, 7011, 7012, 7013, 7014, 7015, 7016, 7017, 7018, 7019, 7020, 7021, 7023, 7024, 7025, 7061, 7062, 7064, 7065, 7066, 7068, 7069, 7070, 7071, 7072, 7073, 7074, 7075, 7076, 7077, 7078, 7079, 7080, 7083, 7084, 7085, 7087, 7089, 7090, 7091, 7092, 7093, 7094, 7095, 7096, 7098, 7099, 7100, 7101, 7102, 7103, 7105, 7106, 7107, 7108, 7109, 7111, 7112, 7113, 7116, 7128, 7129, 7130, 7131, 7136, 7137, 7338, 7451, 7633, 7117, 7348, 7399, 7400, 7489, 7540, 7631, 24265, 24576, 34966, 35025, 35092, 35209, 35287, 35344, 35371, 35400, 35414, 35468, 35490, 35543, 35598, 35706, 35718, 35757, 35838, 35890, 35944, 36001, 36039, 36093, 36117, 36171, 36183, 36192, 38458, 39593, 39667, 39693, 39703, 39777, 39783, 39789, 42683, 44209, 44693, 45536, 45972, 46360, 46749, 48415, 48553, 48703, 48715, 48861, 49619, 49766, 51010, 51792, 52182, 53167, 53171, 53189, 53197, 53211, 53230, 53470, 53472, 53476, 53478, 53480, 53485, 53487, 53489, 53492, 53500, 53503, 53505, 53508, 53511, 53514, 53517, 53520, 53522, 53526, 53529, 53532, 53539, 53542, 53544, 53546, 53549, 53552, 53555, 53557, 53560, 53563, 53566, 53569, 53571, 53586, 53613, 53622, 53626, 53630, 53633, 53636, 53640, 53643, 53647, 53650, 53653, 53657, 53660, 53664, 53670, 53673, 53676, 53679, 53707, 53722, 53739, 53743, 53746, 53749, 53774, 53779, 53791, 53794, 53797, 53801, 53804, 53868, 53887, 53892, 53897, 53900, 53908, 53913, 53918, 53923, 54279, 54282, 54286, 54289, 54292, 54295, 54312, 54340, 54347, 54352, 54435, 54438, 54441, 54444, 54471, 54476, 54594, 54609, 54612, 54616, 54619, 54622, 7135, 35314, 53494, 53617
)
答案 1 :(得分:1)
使用LEFT JOIN ... IS NULL
代替NOT IN ( SELECT ... )
关注wp_postmeta
的索引tips。 (基于EXPLAIN
中的那些巨大数字,这可能会有很大帮助。)
(如果您仍然遇到性能问题,请提供新版本的查询和架构以供进一步批评。)
一些细节......
过去,每个可能的外行都会重新评估IN ( SELECT ... )
。这非常低效。较新版本的MySQL / MariaDB可以执行内部SELECT
一次,但是然后构造一个索引(不是免费的),或者将其转换为NOT EXISTS ( SELECT ... (slightly modified) ... )
;这与LEFT JOIN
相当具竞争力。
此论坛上充斥着IN (...)
和(不常见)NOT IN (...)
的示例。 NOT IN
构造可能比IN
更糟糕。
(对不起,我没有参考,只有多年的经验。)
答案 2 :(得分:1)
如里克所述,应该避免在条款中是否存在,并且存在或不存在。
select col1, col2, col3
from tab1 t1
where exists (select 1 from tab2 where col1 = t1.col1)