mysql 为子查询强制索引

mysql force index for subquery

在这个查询中我们只讨论为子查询设置索引JOIN的能力。不要担心查询的性能

SELECT cate.id, cate.name as category_name, b.id book_id, b.name book_name
FROM categories as cate
LEFT JOIN (select * from books where books.name='some pets 1') as b
ON b.category_id = cate.id;

我想通过使用子查询创建临时 table 'b' 来减少 table 本书的行数,然后尝试为 'b' 强制连接索引但是它不起作用(“force index (category_id)”)。我的草稿代码:

SELECT cate.id, cate.name as category_name, b.id book_id, b.name book_name
FROM categories as cate
LEFT JOIN (select * from books force index (idx_books_name) where books.name='some pets 1') b force index (category_id)
ON b.category_id = cate.id;

它通过 "force index" 处的语法错误。你认为这个想法可能吗?

你的 "subquery" b 是派生的 table。派生的 table 是(基本上)一个全新的 table。这就是您的意图,您想要创建一个小的临时 table b。但是这个新的 table 无法访问原始索引,因为它是一个新的 table。这就是您收到错误消息的原因。

想象一下 MySQL 需要如何使用类别索引。该索引本身没有改变,因此它仍将包含原始 table 的所有行的条目。因此,您将使用该索引在整个 table 中查找具有该 category_id 的记录(因为这就是该索引所做的),然后以某种方式需要检查该条目是否在您的派生 table.由于派生 table 几乎可以包含任何内容,即使没有任何对基 table 的引用,这些也不是执行此操作的通用方法 "somehow".

在您的情况下,这可以通过重新评估条件 where books.name='some pets 1' 来完成,但这意味着您将失去使用 idx_books_name 索引和派生的 table 可能获得的任何优势] 放在第一位,所以它与

相同
LEFT JOIN books b ON b.category_id = cate.id AND b.name='some pets 1');

如果有一个索引 books(category_id, name),它会按照您的预期使用索引。

按照您的方式使用派生的 table 基本上已经是一种优化,它希望防止 MySQL 以通常的方式进行连接(尽管 MySQL 将被允许将您的条件合并回外部查询)。如果你有特殊情况,你会这样做,例如如果只有很少一部分行符合此条件,或者如果您在 category_id.

上没有有用的索引

MySQL 可能决定 generate a new index for your derived table category_id。您(目前)无法通过优化器提示强制生成这些索引,值得注意的是,小 table 上的索引可能没有您想象的那么有用。索引按对数缩放,因此虽然对大 tables 的影响很大,但对于小 tables 来说,生成此类索引的开销可能大于收益。