РСУБД настолько плохи, как описано в Hadoop: Полное руководство?

Я читаю 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)?
11
задан Piotr Czapla 26 November 2010 в 22:59
поделиться