mysql индекс силы для подзапроса - PullRequest
1 голос
/ 05 апреля 2020

В этом запросе мы говорим только о возможности установить индекс 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;

enter image description here

Я хотел бы сократить строки таблиц с помощью подзапроса для создания временная таблица 'b', затем попытайтесь принудительно установить индекс соединения для '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;

Это из-за синтаксической ошибки в «индексе силы». Как вы думаете, возможна ли идея?

1 Ответ

1 голос
/ 06 апреля 2020

Ваш "подзапрос" b является производной таблицей. Производная таблица - это (в основном) совершенно новая таблица. Это то, что вы хотели, вы хотели создать небольшую временную таблицу b. Но эта новая таблица не имеет доступа к исходным индексам, так как это новая таблица. Вот почему вы получаете сообщение об ошибке.

Представьте, как MySQL потребуется использовать индекс категории. Этот индекс сам по себе не изменился, поэтому он по-прежнему будет содержать записи для всех строк исходной таблицы. Таким образом, вы использовали бы этот индекс, чтобы найти записи с этим category_id во всей таблице (как это делает этот индекс), а затем каким-то образом нужно проверить, находится ли эта запись в вашей производной таблице. Поскольку производная таблица может состоять практически из чего угодно, даже без какой-либо ссылки на базовую таблицу, это не универсальный c способ сделать это «как-то».

В вашем случае это можно сделать путем переоценки условие 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');

, что с индексом books(category_id, name) будет использовать индексы, как вы и предполагали.

Использование производной таблицы, как вы это сделали, по сути уже является оптимизацией, которая хочет помешать MySQL выполнить соединение в обычном режиме. путь (хотя MySQL будет разрешено объединить ваше условие обратно во внешний запрос). Вы сделаете это, если у вас есть особые обстоятельства, например, если есть только очень небольшой процент строк, соответствующих этому условию, или если у вас нет полезного индекса для category_id.

MySQL может решить создать новый индекс для вашей производной таблицы на category_id. Вы (в настоящее время) не можете принудительно генерировать эти индексы с помощью подсказок оптимизатора, и стоит отметить, что индексы для небольших таблиц могут быть не такими полезными, как вы думаете. Индексы масштабируются логарифмически, поэтому, хотя эффект для больших таблиц огромен, для небольших таблиц затраты на создание такого индекса могут быть больше, чем выгода.

...