Я читаю Hadoop: полное руководство Тома Уайта. В главе 13.6 «HBase vs RDMS» он сказал, что если у вас много данных, даже простые запросы, такие как получение 10 недавних элементов, чрезвычайно дороги, и им пришлось переписывать их с использованием python и PL / SQL.
Он дает следующее запрос в качестве примера:
SELECT id, stamp, type FROM streams
WHERE type IN ('type1','type2','type3','type4',...,'typeN')
ORDER BY stamp DESC LIMIT 10 OFFSET 0;
И говорит: «Планировщик запросов РСУБД обрабатывает этот запрос следующим образом:
MERGE (
SELECT id, stamp, type FROM streams
WHERE type = 'type1' ORDER BY stamp DESC,
...,
SELECT id, stamp, type FROM streams
WHERE type = 'typeK' ORDER BY stamp DESC
) ORDER BY stamp DESC LIMIT 10 OFFSET 0;
Проблема в том, что мы ищем даже такие простые запросы, как получение 10 последних элементов, чрезвычайно дороги ...
Я читаю Hadoop: подробное руководство Тома Уайта. В главе 13.6 «HBase vs RDMS» он сказал, что если у вас много данных, даже простые запросы, такие как получение 10 недавних элементов, чрезвычайно дороги, и им пришлось переписывать их с использованием python и PL / SQL.
Он дает следующее запрос в качестве примера:
SELECT id, stamp, type FROM streams WHERE type IN ('type1','type2','type3','type4',...,'typeN') ORDER BY stamp DESC LIMIT 10 OFFSET 0;
И говорит: «Планировщик запросов РСУБД обрабатывает этот запрос следующим образом:
MERGE ( SELECT id, stamp, type FROM streams WHERE type = 'type1' ORDER BY stamp DESC, ..., SELECT id, stamp, type FROM streams WHERE type = 'typeK' ORDER BY stamp DESC ) ORDER BY stamp DESC LIMIT 10 OFFSET 0;
Проблема в том, что мы ищем даже такие простые запросы, как получение 10 последних элементов, чрезвычайно дороги ...
Я читаю Hadoop: подробное руководство Тома Уайта. В главе 13.6 «HBase vs RDMS» он сказал, что если у вас много данных, даже простые запросы, такие как получение 10 недавних элементов, чрезвычайно дороги, и им пришлось переписывать их с использованием python и PL / SQL.
Он дает следующее запрос в качестве примера:
SELECT id, stamp, type FROM streams WHERE type IN ('type1','type2','type3','type4',...,'typeN') ORDER BY stamp DESC LIMIT 10 OFFSET 0;
И говорит: «Планировщик запросов РСУБД обрабатывает этот запрос следующим образом:
MERGE ( SELECT id, stamp, type FROM streams WHERE type = 'type1' ORDER BY stamp DESC, ..., SELECT id, stamp, type FROM streams WHERE type = 'typeK' ORDER BY stamp DESC ) ORDER BY stamp DESC LIMIT 10 OFFSET 0;
Проблема в том, что мы ищем только первые 10 идентификаторов, но запрос планировщик фактически материализует все слияние, а затем ограничения на конец. .... Мы фактически зашли так далеко, что написать собственный скрипт PL / Python который выполнил heapsort. ... В почти во всех случаях это превзошло собственная реализация SQL и стратегия планировщика запросов ...
Ожидаемая производительность и экспериментальные результаты
Я не мог представить себе набор данных, который вызовет такие проблемы, что вам придется написать pl / python, чтобы правильно выполнять такой простой запрос. Итак, я некоторое время размышлял об этой проблеме и пришел к следующим наблюдениям:
Производительность такого запроса ограничена O (KlogN). Потому что это можно перевести примерно так:
SELECT * FROM ( SELECT id, stamp, type FROM streams WHERE type = 'type1' ORDER BY stamp DESC LIMIT 10, UNION ..., SELECT id, stamp, type FROM streams WHERE type = 'typeK' ORDER BY stamp DESC LIMIT 10 ) t ORDER BY stamp DESC LIMIT 10;
(обратите внимание на «LIMIT 10» в каждом запросе. Кстати, я знаю, что я не могу ограничивать и упорядочивать объединения, но я вырезал обертывающие выборки для удобства чтения)
Каждый подзапрос должен выполняться с такой же скоростью, как поиск нужной позиции в индексе O (logN) и возврат 10 элементов. Если мы повторим это K раз, мы получим O (KlogN).
И даже если планировщик запросов настолько плох, что не может оптимизировать первый запрос, мы всегда можем преобразовать его в запрос с объединениями и получить желаемую производительность, не записывая ничего в pl / python.
Чтобы дважды проверить мои вычисления Я выполнил запросы выше одного postgresql, заполненного 9000000 тестовых записей. Результаты подтвердили мои ожидания: оба запроса были довольно быстрыми: 100 мс для первого запроса и 300 мс для второго (тот, который был с объединениями).
Таким образом, если запрос выполняется за 100 мс для 9 000 000 (logn = 23) записей, то для 9 000 000 000 (logn = 33) записей он должен выполняться за 140 мс.
Вопросы
- Видите ли вы какие-либо недостатки в приведенных выше рассуждениях ?
- Можете ли вы представить себе набор данных, в котором вам нужно было бы переписать такой запрос, как указано выше, в pl / python?
- Видите ли вы ситуацию, в которой такой запрос не будет ' t работать в O (K log n)?