Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 为什么子查询比连接快?_Mysql_Mysql 5.6 - Fatal编程技术网

Mysql 为什么子查询比连接快?

Mysql 为什么子查询比连接快?,mysql,mysql-5.6,Mysql,Mysql 5.6,慢: 快速 模式: SELECT `m`.`id`, (SELECT `number` FROM `history` WHERE `memb_id` = `m`.`id` ORDER BY `id` DESC LIMIT 1) AS `number`, (SELECT `message` FROM `history` WHERE `memb_id` = `m`.`id` ORDER BY `id` DESC LIMIT 1) AS `message`,

慢:

快速

模式:

SELECT `m`.`id`,
       (SELECT `number`  FROM `history` WHERE `memb_id` = `m`.`id` ORDER BY `id` DESC LIMIT 1) AS `number`,
       (SELECT `message` FROM `history` WHERE `memb_id` = `m`.`id` ORDER BY `id` DESC LIMIT 1) AS `message`,
       (SELECT `code`    FROM `history` WHERE `memb_id` = `m`.`id` ORDER BY `id` DESC LIMIT 1) AS `code`
  FROM `members` AS `m`
    LEFT JOIN `reads`  AS `r` ON `r`.`email` = `m`.`id`
    LEFT JOIN `writes` AS `w` ON `w`.`email` = `m`.`id`
  WHERE `m`.`status` = 1
    AND (`r`.`reads` > 0 OR `w`.`writes` > 0)
  GROUP BY `m`.`id`
;

-- members  ~ 40k
-- history  ~ 400k
-- reads    ~ 40k
-- writes   ~ 4k
-- Query duration: 0.328 sec.

-- members  ~ 40k
-- history  ~ 400k
-- reads    ~ 400k
-- writes   ~ 4k
-- Query duration: 0.343 sec.

如上所述,您的查询不是等价的。“慢速”查询获取成员的所有历史记录,然后使用GROUP BY缩小结果范围。这意味着在短时间内可能存在大量数据,但数字、消息和代码的值很可能没有引用最新的历史记录

针对子查询添加联接以获取每个成员的最新历史记录id,请尝试以下操作:-

CREATE TABLE `members` (
    `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(254) NOT NULL,
    `email` VARCHAR(254) NOT NULL,
    `password` VARCHAR(254) NOT NULL,
    `status` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`),
    INDEX `status` (`status`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;

CREATE TABLE `recipients_history` (
    `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
    `memb_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
    `number` INT(3) UNSIGNED NOT NULL DEFAULT '0',
    `message` TEXT NOT NULL,
    `code` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0',
    `datetime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    INDEX `memb_id` (`memb_id`),
    INDEX `number` (`number`),
    INDEX `code` (`code`),
    INDEX `datetime` (`datetime`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;

-- writes uses the same schema
CREATE TABLE `reads` (
    `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
    `memb_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
    `reads` INT(11) UNSIGNED NOT NULL DEFAULT '1',
    PRIMARY KEY (`id`),
    INDEX `memb_id` (`memb_id`),
    INDEX `reads` (`reads`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;

你用更多的数据检查过了吗?这也可能因获取的数据量而异。您遗漏了一些重要信息。例如:返回多少个结果?这两个查询的执行计划是什么?使用子查询不能很好地扩展,但是对于较小的结果集,它可能会更快。比较执行计划。他们会告诉你发生了什么。尝试使用。两个版本的查询正在做不同的事情;带有
JOIN
的版本不会限制结果集大小,而版本子查询会限制结果集大小(例如
限制1
)。根据您在
历史记录中拥有的内容,这些可能会非常不同。
CREATE TABLE `members` (
    `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(254) NOT NULL,
    `email` VARCHAR(254) NOT NULL,
    `password` VARCHAR(254) NOT NULL,
    `status` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`),
    INDEX `status` (`status`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;

CREATE TABLE `recipients_history` (
    `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
    `memb_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
    `number` INT(3) UNSIGNED NOT NULL DEFAULT '0',
    `message` TEXT NOT NULL,
    `code` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0',
    `datetime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    INDEX `memb_id` (`memb_id`),
    INDEX `number` (`number`),
    INDEX `code` (`code`),
    INDEX `datetime` (`datetime`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;

-- writes uses the same schema
CREATE TABLE `reads` (
    `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
    `memb_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
    `reads` INT(11) UNSIGNED NOT NULL DEFAULT '1',
    PRIMARY KEY (`id`),
    INDEX `memb_id` (`memb_id`),
    INDEX `reads` (`reads`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;
SELECT m.id,
       h.number,
       h.message,
       h.code
FROM members AS m
LEFT OUTER JOIN
(
    SELECT memb_id, MAX(id) as max_id
    FROM history
    GROUP BY memb_id
) sub1 ON m.id = sub1.memb_id
LEFT OUTER JOIN history h ON sub1.memb_id = h.memb_id AND sub1.max_id = h.id
LEFT JOIN reads  AS r ON r.email = m.id
LEFT JOIN writes AS w ON w.email = m.id
WHERE m.status = 1
AND (r.reads > 0 OR w.writes > 0)