Как стать автором
Обновить

Комментарии 5

Эта задача решается быстрее на Oracle, чем на MS SQL

Любая задача быстрее решается тем инструментом, которым лучше владеешь. Бегло посмотрел код на MSSQL — мне кажется там много где можно докрутить — типы курсоров, оконные функции, детерминирование функции TRUNC_UT и т.д. А вообще задача довольно простая — зачем так много вариантов перебирать и сравнивать сервера — что в итоге хотели получить?
зачем так много вариантов перебирать
Когда запрос выполняется 5 секунд, его, разумеется, никто не станет оптимизировать.
Но если запрос выполняется час или день — полагаю, у каждого
разработчика БД или DBA возникнет вопрос, а можно ли его оптимизировать?
и сравнивать сервера
Просто есть опыт 4.5 года и на MS SQL, запустил и там. Цели «сравнить» не было
посмотрел код на MSSQL — мне кажется там много где можно докрутить
Возможно код, возможно сервер, но кроме оконных функций
Оконные функции использовать можно в подобных запросах — в этом случае можно не делать соединения таблицы самой с собой — иногда это выгодно. Вопрос производительности — это уже другой вопрос.
Скорее всего на практике вам не потребуются все данные, а только определённый объём за период и по определённому таймфрейму — это может привести совсем к другим показателям.
И очень странные результаты тестирования варианта CALC — как может вариант, где всё заранее посчитано и сложено в таблицу медленнее какого-то другого?
И ещё вот тут — min (1000000 * cast (UT as bigint) + ID) — маловато будет смещение для 11 млн записей. Да и не нужно такие сложности — достаточно просто min(ID) сделать.
Оконные функции использовать можно в подобных запросах
Убедил. Я написал вариант WIND для двух движков. Но чтобы его протестировать на производительность нужно время. Наверное, в выходные. Ранее меня пугало слово distinct, я считал, что это будет лишний шаг. Если получу удовлетворительные результаты — я добавлю в пост в пул вариантов с указанием ссылки на тебя. Годится? Или можешь опубликовать его здесь сам.
Скорее всего на практике вам не потребуются все данные, а только определённый объём
Тут, также как в DWH. Действительно, в каждый конкретный момент времени нам требуется небольшой кусочек данных, но за день окажется что мы опросили большую часть всего объёма, и некоторые части — многократно (и многократно же их рассчитывали). Чтобы не тратить время на многократный расчёт — мы загружаем в хранилище все данные, за весь период, и рассчитав однократно.
как может вариант, где всё заранее посчитано и сложено в таблицу медленнее какого-то другого?
Почему? Он не медленнее, он быстрее всего на MS SQL.
?
Можешь связаться со мной, обсудим, отвечу на вопросы
достаточно просто min(ID) сделать
Это моя ошибка. Я исправлю. Просто ранее это поле называлось не ID, а SEQ_NUM, и в нём хранился порядковый номер транзакции внутри секунды. Там окна 10^6 было с запасом. Но потом я отказался от этого поля, потому что требовался дополнительный оператор, который пройдёт по всей таблице и заполнит это поле на основании ID
Хороших результатов с оконными функциями я не добился на MSSQL, так что в данном случае особенно выкладывать думаю нечего и тратить на это время тоже — использование внутри функции расчёта таймфрейма для PARTITION BY несколько раз для каждой цены свечки — не самый хороший вариант:
 DECLARE @STRIPE_ID int = 5
 SELECT dbo.UT2DATESTR(UT), *
   FROM (
 SELECT STRIPE_ID = @STRIPE_ID,
           STOCK_NAME,
           dbo.TRUNC_UT(UT, @STRIPE_ID) AS UT,
           AOPEN = FIRST_VALUE(APRICE) OVER (PARTITION BY dbo.TRUNC_UT(UT, @STRIPE_ID) ORDER BY UT),
           ACLOSE = LAST_VALUE(APRICE) OVER (PARTITION BY dbo.TRUNC_UT(UT, @STRIPE_ID) ORDER BY UT RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING),
           AMAX = MAX(APRICE) OVER (PARTITION BY dbo.TRUNC_UT(UT, @STRIPE_ID) ORDER BY UT RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING),
           AMIN = MIN(APRICE) OVER (PARTITION BY dbo.TRUNC_UT(UT, @STRIPE_ID) ORDER BY UT RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING),
           SORT = ROW_NUMBER() OVER (PARTITION BY dbo.TRUNC_UT(UT, @STRIPE_ID) ORDER BY UT ASC),
           CNT = COUNT(*) OVER (PARTITION BY dbo.TRUNC_UT(UT, @STRIPE_ID)),
           APRICE
 FROM TRANSACTIONS_RAW) x
 WHERE x.SORT = 1

Тут наверное нужно делать предварительный расчёт даты/времени в отдельных колонках таблицы для каждого таймфрейма и потом уже пользоваться ими в запросе.
Вобщем не самый оптимальный вариант.
Что касается скорости метода CALC — то я имел в виду ORACLE — он оказался чуть ли не на последнем месте — просто не хватило индексов в таблице?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории