繁体   English   中英

JOINING 时如何让 MySQL 优化器首先使用我的索引?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM