为什么 STRAIGHT_JOIN 消耗更多 CPU?
Why does STRAIGHT_JOIN consume more CPU?
为什么 STRAIGHT_JOIN 比常规连接消耗更多 CPU?你有什么主意吗?
当我在我的一个查询中使用 straight_join 时,它使查询速度从 12 秒缩短到 3 秒。但是这么耗电CPU?可能与服务器配置或其他问题有关?
您可能需要检查此评论后的代码 / 主题 ID 正常,正在获取设备... /
在这一行之前有一些关于将 topic_ids 填充到临时 table.
的代码
这里是查询:
CREATE PROCEDURE `DevicesByTopic`(IN platform TINYINT, IN application TINYINT, IN topicList TEXT, IN page_no MEDIUMINT UNSIGNED)
BEGIN
DECLARE m_index INT DEFAULT 0;
DECLARE m_topic VARCHAR(255);
DECLARE m_topic_id BIGINT UNSIGNED DEFAULT NULL;
DECLARE m_session_id VARCHAR(40) CHARSET utf8 COLLATE utf8_turkish_ci;
-- Session Id
SET m_session_id = replace(uuid(), '-', '');
-- Temp table
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_topics(
topic_slug VARCHAR(100) COLLATE utf8_turkish_ci
,topic_id BIGINT UNSIGNED
,session_id VARCHAR(40) COLLATE utf8_turkish_ci
,INDEX idx_tmp_topic_session_id (session_id)
,INDEX idx_tmp_topic_id (topic_id)
) CHARSET=utf8 COLLATE=utf8_turkish_ci;
-- Filling topics in a loop
loop_topics: LOOP
SET m_index = m_index + 1;
SET m_topic_id = NULL;
SET m_topic= SPLIT_STR(topicList,',', m_index);
IF m_topic = '' THEN
LEAVE loop_topics;
END IF;
SELECT t.topic_id INTO m_topic_id FROM topic AS t WHERE t.application = application AND (t.slug_hashed = UNHEX(MD5(m_topic)) AND t.slug = m_topic) LIMIT 1;
-- Fill temp table
IF m_topic_id IS NOT NULL AND m_topic_id > 0 THEN
INSERT INTO tmp_topics
(topic_slug, topic_id, session_id)
VALUES
(m_topic, m_topic_id, m_session_id);
END IF;
END LOOP loop_topics;
/* Topic Ids are OK, Getting Devices... */
SELECT
dr.device_id, dr.platform, dr.application, dr.unique_device_id, dr.amazon_arn
FROM
device AS dr
INNER JOIN (
SELECT STRAIGHT_JOIN
DISTINCT
d.device_id
FROM
device AS d
INNER JOIN
device_user AS du ON du.device_id = d.device_id
INNER JOIN
topic_device_user AS tdu ON tdu.device_user_id = du.device_user_id
INNER JOIN
tmp_topics AS tmp_t ON tmp_t.topic_id = tdu.topic_id
WHERE
((platform IS NULL OR d.platform = platform) AND d.application = application)
AND d.page_no = page_no
AND d.status = 1
AND du.status = 1
AND tmp_t.session_id = m_session_id COLLATE utf8_turkish_ci
) dFiltered ON dFiltered.device_id = dr.device_id
WHERE
((platform IS NULL OR dr.platform = platform) AND dr.application = application)
AND dr.page_no = page_no
AND dr.status = 1;
-- Delete rows fFill temp table
DELETE FROM tmp_topics WHERE session_id = m_session_id;
END;
使用 STRAIGHT_JOIN 这个查询大约需要 3 秒但消耗了这么多 CPU 大约 90%,但是如果我删除关键字 "STRAIGHT_JOIN",它需要 12 秒但消耗 12 %CPU。
MySQL 5.6.19a-innodb
可能是什么原因?
此致。
当您需要覆盖 MySQL 的优化器时,使用 STRAIGHT_JOIN
。您告诉它忽略自己的优化执行路径,而是依赖于按照您在查询中编写的顺序读取表。
99% 的时间您不想使用 straight_join
。只需依靠 MySQL 来完成它的工作并为您优化执行路径。毕竟,任何物有所值的 RDBMS 在优化方面都会相当不错。
您应该使用 straight_join
的几次是当您已经测试了 MySQL 对给定查询的优化并发现它缺乏时。在您使用此查询的情况下,显然您使用 straight_join
进行的手动优化并不比 MySQL 的优化更好。
为什么 STRAIGHT_JOIN 比常规连接消耗更多 CPU?你有什么主意吗?
当我在我的一个查询中使用 straight_join 时,它使查询速度从 12 秒缩短到 3 秒。但是这么耗电CPU?可能与服务器配置或其他问题有关?
您可能需要检查此评论后的代码 / 主题 ID 正常,正在获取设备... /
在这一行之前有一些关于将 topic_ids 填充到临时 table.
这里是查询:
CREATE PROCEDURE `DevicesByTopic`(IN platform TINYINT, IN application TINYINT, IN topicList TEXT, IN page_no MEDIUMINT UNSIGNED)
BEGIN
DECLARE m_index INT DEFAULT 0;
DECLARE m_topic VARCHAR(255);
DECLARE m_topic_id BIGINT UNSIGNED DEFAULT NULL;
DECLARE m_session_id VARCHAR(40) CHARSET utf8 COLLATE utf8_turkish_ci;
-- Session Id
SET m_session_id = replace(uuid(), '-', '');
-- Temp table
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_topics(
topic_slug VARCHAR(100) COLLATE utf8_turkish_ci
,topic_id BIGINT UNSIGNED
,session_id VARCHAR(40) COLLATE utf8_turkish_ci
,INDEX idx_tmp_topic_session_id (session_id)
,INDEX idx_tmp_topic_id (topic_id)
) CHARSET=utf8 COLLATE=utf8_turkish_ci;
-- Filling topics in a loop
loop_topics: LOOP
SET m_index = m_index + 1;
SET m_topic_id = NULL;
SET m_topic= SPLIT_STR(topicList,',', m_index);
IF m_topic = '' THEN
LEAVE loop_topics;
END IF;
SELECT t.topic_id INTO m_topic_id FROM topic AS t WHERE t.application = application AND (t.slug_hashed = UNHEX(MD5(m_topic)) AND t.slug = m_topic) LIMIT 1;
-- Fill temp table
IF m_topic_id IS NOT NULL AND m_topic_id > 0 THEN
INSERT INTO tmp_topics
(topic_slug, topic_id, session_id)
VALUES
(m_topic, m_topic_id, m_session_id);
END IF;
END LOOP loop_topics;
/* Topic Ids are OK, Getting Devices... */
SELECT
dr.device_id, dr.platform, dr.application, dr.unique_device_id, dr.amazon_arn
FROM
device AS dr
INNER JOIN (
SELECT STRAIGHT_JOIN
DISTINCT
d.device_id
FROM
device AS d
INNER JOIN
device_user AS du ON du.device_id = d.device_id
INNER JOIN
topic_device_user AS tdu ON tdu.device_user_id = du.device_user_id
INNER JOIN
tmp_topics AS tmp_t ON tmp_t.topic_id = tdu.topic_id
WHERE
((platform IS NULL OR d.platform = platform) AND d.application = application)
AND d.page_no = page_no
AND d.status = 1
AND du.status = 1
AND tmp_t.session_id = m_session_id COLLATE utf8_turkish_ci
) dFiltered ON dFiltered.device_id = dr.device_id
WHERE
((platform IS NULL OR dr.platform = platform) AND dr.application = application)
AND dr.page_no = page_no
AND dr.status = 1;
-- Delete rows fFill temp table
DELETE FROM tmp_topics WHERE session_id = m_session_id;
END;
使用 STRAIGHT_JOIN 这个查询大约需要 3 秒但消耗了这么多 CPU 大约 90%,但是如果我删除关键字 "STRAIGHT_JOIN",它需要 12 秒但消耗 12 %CPU。
MySQL 5.6.19a-innodb
可能是什么原因?
此致。
当您需要覆盖 MySQL 的优化器时,使用 STRAIGHT_JOIN
。您告诉它忽略自己的优化执行路径,而是依赖于按照您在查询中编写的顺序读取表。
99% 的时间您不想使用 straight_join
。只需依靠 MySQL 来完成它的工作并为您优化执行路径。毕竟,任何物有所值的 RDBMS 在优化方面都会相当不错。
您应该使用 straight_join
的几次是当您已经测试了 MySQL 对给定查询的优化并发现它缺乏时。在您使用此查询的情况下,显然您使用 straight_join
进行的手动优化并不比 MySQL 的优化更好。