Я довольно неопытен с базами данных и только что прочитал о "n+1 selects issue". Мой вопрос о последующих действиях: Предполагая, что база данных находится на том же компьютере, что и моя программа, кэшируется в ОЗУ и правильно индексируется, почему шаблон запроса n + 1 замедляется?Почему n + 1 выбирает шаблон медленным?
В качестве примера давайте возьмем код из принятого ответа:
SELECT * FROM Cars;
/* for each car */
SELECT * FROM Wheel WHERE CarId = ?
С моей ментальной моделью кэша базы данных, каждый из SELECT * FROM Wheel WHERE CarId = ?
запросов должен нуждаться:
- 1 поиск в доведите до стола «Колесо» (один хэш-код
get()
) - 1 поиск, чтобы попасть в список k колес с указанным
CarId
(другой хэш-кодget()
) - K поисков, чтобы получить колесо строк для каждого согласующего колеса (K указатель dereferenciations)
Даже если умножить на небольшой постоянный множитель для дополнительных накладных расходов из-за внутреннюю структуру памяти, она по-прежнему должен быть незаметно быстрым. Является ли межпроцессное общение узким местом?
Edit: Я только что нашел эту статью по теме через Hacker News: Following a Select Statement Through Postgres Internals. - HN discussion thread.
Edit 2: Для того, чтобы уточнить, я сделатьN
предположить, чтобы быть большим. Нетривиальные служебные данные будут содержать заметную задержку, тогда да. Я спрашиваю , почему накладные расходы являются нетривиальными в первую очередь для описанной выше настройки.
Поскольку один оператор извлечения п + 1 строк почти всегда быстрее, чем п + 1 заявления. При анализе SQL возникают проблемы, подготовка плана выполнения и последующее возвращение данных (в зависимости от СУБД, этап синтаксического анализа может быть существенным издержками). И кроме того: читали бы вы рецепт для торта, а затем отправляетесь в супермаркет, чтобы купить муку, идите домой, прочитайте рецепт, вернитесь, купите яйца, идите домой, прочитайте рецепт, вернитесь купить масло, ... –
«Поскольку одно утверждение, извлекающее n + 1 строки, почти всегда быстрее, чем n + 1 операторов.«Я вижу это, но я удивлен, что это занимает намного больше времени, когда люди, пишущие свои программы в Ruby или Python, а не C, действительно заботятся. Решения, которые я нашел, иногда выглядят значительно сложнее исходного кода. если бы ингредиенты были только в другой комнате, мне бы, наверное, было бы не слишком важно переходить дважды или трижды;). – Perseids
Повторный анализ синтаксического анализа: учитывая, что мы уже используем подготовленные заявления повсюду, разве это не то, что хорошо развитая библиотека должна (@a_horse_with_no_name) – Perseids