我有一个包含三个相关表的MySQL数据库, t1 有 6598 行, t2 有 1713 行和 t3 和 10023 行。
详细信息:
TABLE t1 (
`id` SERIAL,
`t2_id` BIGINT UNSIGNED NOT NULL,
`t3_id` BIGINT UNSIGNED,
PRIMARY KEY (`id`),
FOREIGN KEY (t2_id) REFERENCES t2(id),
FOREIGN KEY (t3_id) REFERENCES t3(id)
);
TABLE t2(
`id` SERIAL,
`name` VARCHAR(128) NOT NULL,
PRIMARY KEY (`id`)
);
TABLE t3 (
`id` SERIAL,
`name` VARCHAR(128),
PRIMARY KEY (`id`)
);
我想执行以下查询,但是查询没有完成(基本上会永远占用):
SELECT *
FROM t1
INNER JOIN t3
ON t1.t3_id = t3.id
INNER JOIN t2
ON t1.t2_id = t2.id
WHERE (t3.name NOT NULL)
ORDER BY t3.name ASC , t1.id ASC
LIMIT 25
当我删除订单条款时,它的工作速度非常快(0.17秒)。
如何更改查询以使其正常工作?
答案 0 :(得分:1)
我可以建议以下指标:
CREATE INDEX idx_t1 ON t1 (t2_id, t3_id, id);
CREATE INDEX idx_t3 ON t3 (id, name);
这些索引至少应该大大加快连接速度。如果使用MySQL,很可能会采取以下加入策略:
SELECT *
FROM t2
INNER JOIN t1
ON t2.id = t1.t2_id
INNER JOIN t3
ON t1.t3_id = t3.id
WHERE
t3.name IS NOT NULL
ORDER BY
t3.name,
t1.id
LIMIT 25;
这里的想法是我们对t2
进行全表扫描,这是迄今为止最小的表。无论如何,t2
中的记录没有限制,所以我们最好先扫描一下。然后,对于t1
和t3
的每个联接,我们尝试使用索引设置。请注意,由于表中的列相对较少,因此定义的两个索引可以轻松覆盖所有列,从而增加了MySQL选择使用索引的可能性。
答案 1 :(得分:0)
t1
是一个多对多映射表。它不需要PK的替代id
。相反,它需要其他两列的组合PK,再加上另一个方向的索引。
有关这些内容和其他一些提示的讨论,请参见http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table。