Обновление агрегированных таблиц с новой последовательностью - PullRequest
0 голосов
/ 24 мая 2018

Общий сценарий:

У меня есть сводная таблица на пользователя и дату с несколькими показателями.в таблице хранится до 10 записей на пользователя и дату (может быть меньше, в зависимости от активности пользователя). Существует столбец, который представляет собой последовательность событий, упорядоченную по дате.

Пример:

CREATE TABLE #Main (UserId int , DateId int , MeasureA numeric(20,2) , MeasureB numeric(20,2), PlayDaySeq int)
INSERT INTO #Main 
    VALUES (188,    20180522    ,75.00,     282287.00,  1),
           (188,    20180518    ,250.00,    1431725.00, 2),
           (188,    20180514    ,25.00,     35500.00,   3),
           (188,    20180513    ,115.00,    67100.00,   4),
           (188,    20180511    ,75.00,     10625.00,   5),
           (188,    20180510    ,40.00,     2500.00,    6),
           (188,    20180509    ,40.00,     750.00,     7),
           (188,    20180508    ,160.00,    16250.00,   8),
           (188,    20180507    ,135.00,    138200.00,  9),
           (188,    20180507    ,150.00,    68875.00,   10)

Столбец PlayDaySeq рассчитывается как ROW_NUMBER () OVER (PARTITION BY UserID ORDER BY DateId DESC)

, и вот таблица, в которой будут храниться новые агрегированные данные для этого пользователя:

CREATE TABLE #Inc (UserId int , DateId int , MeasureA numeric(20,2) , MeasureB numeric(20,2), PlayDaySeq int)
INSERT INTO #Inc
    VALUES (188,    20180523    ,225.00,    802921.00,  1)

Теперь новая записьдоступно, поэтому я использовал следующее:

INSERT INTO #Main
    SELECT * 
     FROM #Inc I
        WHERE NOT EXISTS 
            (
            SELECT 1 
            FROM #Main M
            WHERE i.UserId = M.UserId
            AND i.DateId = M.DateId
            )

Вопрос:

Мне нужно обновить столбец PlayDaySeq, чтобы новая запись была 1 и всеостальные увеличатся на 1 и удалят записи о том, что их последовательность будет больше 10

Каков наилучший способ сделать это?имейте в виду, что таблица #main довольно большая (250M записей).

Я могу обновить последовательность, снова запустив ROW_NUMBER, а затем DELETE те, которые будут больше 10, яищу наиболее эффективный способ сделать это.

1 Ответ

0 голосов
/ 24 мая 2018

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

Я предлагаю перетащить PlayDaySeq на стол и создать представление со следующим в качестве дополнительного столбца.

ROW_NUMBER () OVER (PARTITION BY UserID ORDER BY DateId DESC) AS PlayDaySeq

А затемНезависимо от того, что ваш код использовал эту таблицу, теперь следует использовать представление, поэтому изменения должны быть минимальными.Но вам нужно проверить это, посмотреть, какова производительность.Кроме того, если вы измените представление на индексированное представление, SQL-сервер сохранит значение в виде табличного элемента, который при вставке новой записи автоматически обновит данные для вас, опять же, вам потребуется тестовая производительность при вставке.

Если бы я был вами, я бы с большей готовностью попробовал другой подход, например, вместо того, чтобы сделать его 1,2,3, я установил его на 100,200,300, следовательно, когда потребность в вставке меньше, например, 20 записей в день, мне больше не нужно обновлять оставшуюся записьно просто вставьте 11,12 101,102, который по-прежнему будет содержать правильный порядок, и ночную работу по обновлению всей таблицы, чтобы она снова стала 100,200,300 для нового начала на следующий день, или создайте код, который будет делать это только при исчерпании чисел,но из-за того, как вы используете его, когда формулируете это другое значение, он может вообще не работать.

...