简体   繁体   English

mysql 子查询的强制索引

[英]mysql force index for subquery

in this query we only talk about the ability to set the index JOIN for the subquery.在这个查询中,我们只讨论为子查询设置索引 JOIN 的能力。 Don't concern about the performance of the query不关心查询的性能

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;

在此处输入图像描述

I would like to reduce rows of table books by using sub-query to create temporary table 'b', then try to force join index for 'b' but it didn't work (" force index (category_id) ").我想通过使用子查询创建临时表'b'来减少表书的行,然后尝试为'b'强制连接索引但它不起作用(“强制索引(category_id) ”)。 My draft code:我的草稿代码:

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;

It through the syntax error at "force index".它通过“强制索引”处的语法错误。 Is the idea possible, you think?你觉得这个想法可能吗?

Your "subquery" b is a derived table.您的“子查询” b 是派生表。 A derived table is (basically) a completely new table.派生表(基本上)是一个全新的表。 This is what you intended, you wanted to create a small temporary table b .这就是您的意图,您想创建一个小型临时表b But this new table has no access to the original indexes, as it is a new table.但是这个新表无法访问原始索引,因为它是一个新表。 This is why you get the error message.这就是您收到错误消息的原因。

Imagine how MySQL would need to use the category index.想象一下 MySQL 需要如何使用类别索引。 That index itself didn't change, so it will still contain entries for all rows of the original table.该索引本身没有改变,因此它仍将包含原始表的所有行的条目。 So you would use this index to find records with that category_id in the whole table (as that is what this index does), and then somehow need to check if that entry is in your derived table.因此,您将使用此索引在整个表中查找具有该category_id的记录(正如该索引所做的那样),然后以某种方式需要检查该条目是否在您的派生表中。 Since a derived table can consist of virtually anything, even without any reference to a base table, these is no generic way to do this "somehow".由于派生表几乎可以包含任何内容,即使没有对基表的任何引用,这些都不是“以某种方式”执行此操作的通用方法。

In your case, this could be done by reevaluating the condition where books.name='some pets 1' , but this would mean you lose any advantage you might get from using the idx_books_name index and your derived table in the first place, so it would be the same as在您的情况下,这可以通过重新评估where books.name='some pets 1'的条件来完成,但这意味着您首先会失去使用idx_books_name索引和派生表可能获得的任何优势,所以它将与

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

which would, with an an index books(category_id, name) , be using indexes as you intended.这将使用索引books(category_id, name) ,按照您的意图使用索引。

Using the derived table the way you did is basically already an optimization that wants to prevent MySQL from doing the join in the usual way (although MySQL would be allowed to merge your condition back into the outer query).以您所做的方式使用派生表基本上已经是一种优化,它希望阻止 MySQL 以通常的方式进行连接(尽管 MySQL 将被允许将您的条件合并回外部查询)。 You'll do this if you have special circumstances, eg if there is only a very small percentage of rows that match this condition or if you don't have a useful index on category_id .如果您有特殊情况,您将执行此操作,例如,如果只有很小比例的行符合此条件,或者您在category_id上没有有用的索引。

MySQL might decide to generate a new index for your derived table on category_id . MySQL 可能决定在category_id为您的派生表生成一个新索引 You (currently) cannot enforce generating those indexes by optimizer hints, and it is worth noting that indexes on small tables may not be as useful as you might think.您(当前)无法通过优化器提示强制生成这些索引,值得注意的是,小表上的索引可能没有您想象的那么有用。 Indexes scale logarithmically, so while the effect on large tables is huge, for small tables the overhead of generating such an index might be larger than the benefit.索引以对数方式扩展,因此虽然对大表的影响很大,但对于小表,生成此类索引的开销可能大于收益。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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