Держите сумму счета правильно, не теряя производительности? - PullRequest
0 голосов
/ 07 октября 2019

У меня есть две таблицы ...

CREATE TABLE [dbo].[Invoice](
    [InvoiceID] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
    [TotalSumBeforeTax] [decimal](12, 2) NOT NULL,
    [TotalSumAfterTax] [decimal](12, 2) NOT NULL
)

CREATE TABLE [dbo].[InvoiceItem](
    [InvoiceItemID] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
    [InvoiceID] [uniqueidentifier] NOT NULL,
    [AmountBeforeTax] [decimal](12, 2) NOT NULL,
    [AmountAfterTax] [decimal](12, 2) NOT NULL
) 

Таблица счетов содержит рассчитанную сумму всех InvoiceItems, которые относятся к этому счету.

Мне нужна помощь в выясненииЛучшая практика для правильного сохранения суммы счета-фактуры без потери производительности.

Расчетный столбец?

Если я использую вычисленный столбец для TotalSumBeforeTax и TotalSumAfterTax в счете-фактуретаблица, которая извлекает значения через функцию из таблицы InvoiceItem, она не сохраняется и будет очень медленной, поскольку у меня в таблице InvoiceItem есть сотни тысяч строк.

Триггер?

Я также думал об использовании триггера для таблицы InvoiceItem и последующем обновлении столбцов Invioce TotalSumBeforeTax TotalAfterBeforeTax.

Что делать?

Есть ли способ всегда поддерживать столбцы TotalSumBeforeTax и TotalSumAfterTax в актуальном состоянии с минимальным влиянием на производительность при перечислении многих строк таблицы Invoice?

Ответы [ 2 ]

2 голосов
/ 07 октября 2019

Я бы сказал, что вам не следует хранить эти столбцы вообще. Просто создайте индекс для таблицы InvoiceItem, который будет иметь InvoiceID и будет включать столбцы AmountBeforeTax и AmountAfterTax, и при необходимости вычислитесь с использованием простого запроса sum и group by:

SELECT InvoiceID
    , SUM(AmountBeforeTax) AS TotalSumBeforeTax
    , SUM(AmountAfterTax) AS TotalSumAfterTax
FROM dbo.InvoiceItem
GROUP BY InvoiceID

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

Кстати, если есть налог, не следуетэто будет price а не amount?

1 голос
/ 07 октября 2019

ТЛ; др;Начните с представления, затем, если / когда необходимо, измените на индексированное представление.

Я бы изначально создал представление для вашей таблицы счетов, например

create view dbo.InvoiceView
as
SELECT I.* -- Don't actually use *, spell out all your columns
  , (select SUM(AmountBeforeTax) from dbo.InvoiceItem II where II.InvoiceId = I.InvoiceId) AS TotalSumBeforeTax
  , (select SUM(AmountAfterTax) from dbo.InvoiceItem II where II.InvoiceId = I.InvoiceId) AS TotalSumAfterTax
FROM dbo.Invoice I;

с (по крайней мере)index на dbo.InvoiceItem.InvoiceId.

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

CREATE UNIQUE CLUSTERED INDEX CX_InvoiceId
   ON dbo.InvoiceView (InvoiceID); -- And any other relevant columns
GO

, который под капотом аналогичен эффекту создания триггера, но выне нужно управлять этим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...