Эффективный SQL-запрос "OFFSET x ROWS FETCH NEXT x ROWS ONLY" с надписью "TOP (x) WITH TIES" вокруг него - PullRequest
0 голосов
/ 02 ноября 2018

Мне нужен эффективный способ нарезки результатов SQL-запроса 'JOIN' на сплошные блоки для одновременной обработки.

У меня есть две таблицы, используемые в этом запросе, которые я назову C и P.

C содержит следующие поля: C_CID, C_f1, C_f2

P содержит следующие поля: P_CID, P_Cat, P_Order, P_f3, P_f4

Идея состоит в том, что элементы P являются частью элементов C.

Первый запрос выглядит следующим образом:

SELECT P_CID, C_f1, C_f2, P_Cat, P_Order, P_f3, P_f4
FROM C JOIN P ON C_CID = P_CID
ORDER BY P_CID, P_Cat, P_Order

Довольно просто. Теперь, чтобы использовать результат этого запроса, мне нужно было бы проверять строку за строкой, если я все еще использую один и тот же C_CID, так что ничего страшного, но он медленный.

Затем я предположил, что что-то вроде OFFSET и FETCH будет существовать по поведению db mgmnt GUI, который я часто использую, и вот, вот они, ожидая, что я их использую, так что все в порядке, и я пытаюсь выполнить второй запрос .

Это в основном то же самое с добавленным 'OFFSET% d ROWS FETCH NEXT% d ROWS ONLY' в конце, и я перемещаю некоторый код, чтобы привыкнуть к изменению: несколько потоков, каждый с доступом к базе данных, и чтение результата часть приходит позже, но я могу использовать данные прямо из БД, и мне нужно обновить смещение, добавив желаемое количество строк после построения запроса, которое в мьютексе я использую в своих совершенно новых потоках X.

Я выбираю около ста рядов по блокам (общий размер соединения составляет Xe ^ 6) и 8 потоков только потому, что нажимаю play и сразу же растапливаюсь из-за увеличения скорости.

А потом я проверяю результаты и о, Боже.

По сути, так как я произвольно разрезал таблицу на куски, группа элементов C с несколькими P-частями получила некоторые в конце фрагмента, а некоторые в начале следующего, aaand разбился и теперь отсутствует, и воздух начинает пахнуть моим поражением.

Я смотрю вещи и узнаю о TOP (x) WITH TIES. Что он делает, так это то, что в конце фрагмента, если последний элемент и следующий связаны столбцами в предложении ORDER BY, он добавляет его в блок (рекурсивно так).

"Выглядит хорошо", я думаю. «Теперь, как мне использовать это со смещением?»

Так что я обдумываю кое-что, осматриваю еще кое-что (31510742) и придумываю это:

WITH TEMP AS
(SELECT P_CID, P_Cat, P_Order, C_f1, C_f2, P_f3, P_f4
FROM C JOIN P ON C_CID = P_CID
ORDER BY P_CID, P_Cat, P_Order
OFFSET %d ROWS)
SELECT * FROM
(SELECT TOP %d WITH TIES *
FROM TEMP
ORDER BY P_CID)
AS TEMP2
ORDER BY P_CID, P_Cat, P_Order

(я знаю, что SELECT * FROM (SELECT) выглядит плохо, но мне нужно полное предложение ORDER BY, чтобы оно не было слишком конкретным для TOP OF TIES).

И это не работает.

Быстрое мышление, и я понимаю, что все еще обновляю смещение на статическую величину.

Теперь я должен сделать дополнительный COUNT (*) из всего этого, прежде чем выйти из мьютекса, но, эй, у меня полно потоков, работающих на полной скорости, так что это все равно победа, верно?

правый ..

Так стало так медленно.

Как оказалось, SELECT с СМЕЩЕНИЕМ ВЫБИРАЕТ все, что остается в таблице. Поэтому, хотя я никогда не вижу его, он временно загружает загрузку строк, которые я не буду использовать в этом результате запроса.

Более быстрое мышление, и у меня есть новый запрос:

WITH TEMP AS
(SELECT P_CID, P_Cat, P_Order, C_f1, C_f2, P_f3, P_f4
FROM C JOIN P ON C_CID = P_CID
ORDER BY P_CID, P_Cat, P_Order
OFFSET %d ROWS
FETCH NEXT %d + %d ROWS ONLY)
SELECT * FROM
(SELECT TOP %d WITH TIES *
FROM TEMP
ORDER BY P_CID)
AS TEMP2
ORDER BY P_CID, P_Cat, P_Order

с выборкой, которая творит чудеса. Первый новый% d имеет то же значение, что и TOP, а второй - это максимальное количество элементов P, прикрепленных к одному и тому же элементу C (COUNTed в начале выполнения однострочным запросом) минус один. Если вы не понимаете, почему просто нарисуйте сценарий наихудшего случая на бумаге: самый мощный элемент C начинается прямо в конце фрагмента. На моих C и P это 20, и я знаю, что это никогда не будет намного больше, так что на самом деле так эффективно делать.

Теперь есть много вещей, работающих вместе, надо работать, ПРАВИЛЬНО?

И это так. Но это безобразно. И есть слишком много вещей, чтобы отслеживать. И это адаптация, когда мне нужно другое поле (* из * того, что я хочу, черт побери). И я просто ЗНАЮ, что должен быть более простой способ сделать это.

Пожалуйста, скажите мне, как.

1 Ответ

0 голосов
/ 02 ноября 2018

Вы знаете, что это глупо, но читая это снова, я действительно мог бы просто «ВЫБЕРИТЕ ТОП (x) С TIES ORDER BY P_CID ASC», сделать еще один ВЫБОР вокруг него с ORDER BY вверх ногами (P_CID DESC), получить первый Значение P_CID (фактически последнее) и выполните следующее «SELECT TOP (X) WITH TIES ORDER BY P_CID ASC» с добавленным предложением «WHERE P_CID>% d»,% d - самый высокий CID, считанный до тех пор.

Ничто не соскребает стены, я могу добавить свои дополнительные столбцы ORDER BY во второй SELECT, чтобы TOP WITH TIES не видел их, есть 0 неиспользуемых строк, которые извлекаются, и код вокруг него удобнее создавать.

Я попробую.

...