[英]How do I tell the MySQL Optimizer to use the index on a derived table?
[英]How can I get MySQL optimizer to use my index first when JOINING?
我有一个 50M 的行表,我正在尝试编写一个查询来导出数据。 表结构的相关子集:
CREATE TABLE `questions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`asked_at` datetime NOT NULL,
`site_id` int(11) NOT NULL,
`account_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `k_site_id_deleted_asked_at` (`site_id`,`deleted`,`asked_at`)
)
和我的 SELECT 的一个子集(真正的有......很多连接)
SELECT
`questions`.`id` AS question_id,
`sites`.`name` AS site_name,
`accounts`.`name` AS account_name
FROM `questions` FORCE INDEX (k_site_id_deleted_asked_at)
INNER JOIN `sites` ON `sites`.`id` = `questions`.`site_id`
INNER JOIN `accounts` ON `questions`.`account_id` = `accounts`.`id`
WHERE `questions`.`asked_at` BETWEEN '2017-07-06 07:00:00' AND '2017-08-07 06:59:59'
AND `questions`.`site_id` IN (<some_numbers>)
AND `questions`.`deleted` = 0
ORDER BY `questions`.`asked_at`;
这个查询不够快; 对于大量的 site_id 和日期,运行需要一分钟以上的时间。 但是,当我从查询中取出sites
上的连接时:
SELECT
`questions`.`question_number`,
`accounts`.`name` AS Account
FROM `questions` FORCE INDEX (k_site_id_deleted_asked_at)
INNER JOIN `accounts` ON `questions`.`account_id` = `accounts`.`id`
WHERE `questions`.`asked_at` BETWEEN '2017-07-06 07:00:00' AND '2017-08-07 06:59:59'
AND `questions`.`site_id` IN (<some_numbers>)
AND `questions`.`deleted` = 0
ORDER BY `questions`.`asked_at`;
它快得令人眼花缭乱——我在大约 50 毫秒内看到我的第一行——即使我有其他疯狂的领域并加入那里。 它刚刚加盟的sites
,这似乎是引起问题。
EXPLAIN
给了我一个关于发生了什么的提示。 当我在那里加入sites
时, sites
被列为EXPLAIN
输出中的第一行。 当我拿出来时, questions
是第一行。
我认为查询优化器正在查看表,说“哦,嘿,我可以比这个questions
更好地限制sites
主键 waaaaay。” 但这是错误的。
有没有办法告诉查询引擎我希望它首先查看questions
?
尝试在进行任何连接之前先对其进行过滤。
SELECT `questions`.`id` AS question_id,
`sites`.`name` AS site_name,
`accounts`.`name` AS account_name
FROM `questions`
INNER JOIN
(SELECT
`id`
FROM `questions` FORCE INDEX (k_site_id_deleted_asked_at)
WHERE `questions`.`asked_at` BETWEEN '2017-07-06 07:00:00' AND '2017-08-07 06:59:59'
AND `questions`.`site_id` IN (<some_numbers>)
AND `questions`.`deleted` = 0
ORDER BY `questions`.`asked_at`) t1 on t1.`id` = `questions`.`id`
INNER JOIN `sites` ON `sites`.`id` = `questions`.`site_id`
INNER JOIN `accounts` ON `questions`.`account_id` = `accounts`.`id`
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.