Есть база на SQL Server 2012 (build 11.0.5343). База используется в качестве DWH, данные в неё загружаю раз в сутки из рабочей базы. Заметил что insert в большую таблицу выполняется достаточно долго, решил спросить можно ли как-либо оптимизировать таблицу/базу/insert.
Сам запрос:
Таблица:
Таблица фактов явно связана с таблицами измерений внешними ключами (с проверкой на существование связанных элементов):
Внешних ключей где-то 15 штук.
Всего на таблице есть 3 некластеризованных уникальных индекса и 1 кластеризованный уникальный по дате.
INSERT-ом добавляются строки за последнюю дату, в основном. Т.е., если в таблице строки до 01.07, то в insert 99% строк будет за 02.07
В таблице около 260 млн строк. Добавление 150000 строк заняло 40 минут. Другие запросы к этой таблице в это время не выполнялись.
Есть какие-либо идеи по оптимизации? Может кусочками в цикле данные добавлять? Или отсортировать их предварительно в таблице temp_tables.dbo.FACT_Sales_Insert (сейчас они расположены в произвольном порядке)?
Предварительный план insert во вложении
Сам запрос:
INSERT INTO dwh.dbo.FACT_Sales( DateID, [Date], DocType, DocID, Number, ParentDocType, ParentDocID, BranchID, BranchStorehouseID, BranchInstallemenID, StaffFirstID, StaffLastID, ContractorID, CustomerID, LegalPersonID, ProjectID, ProductID, SaleSum, AddServiceSum, ExternalServiceSum, InstallmentSum, BonusSum, DiscountSum, VendorDiscountSum, ProductCostSum, ProductCount, ProductPrice, ProductBasePrice, PaymentSum, ProductPriceChangeReasonID, ProductConditionID, _DateLoad, _SourceDB ) SELECT DateID, [Date], DocType, DocID, Number, ParentDocType, ParentDocID, BranchID, BranchStorehouseID, CASE WHEN InstallemenSum IS NOT NULL AND InstallemenSum <> 0 THEN ISNULL(BranchInstallemenID, BranchID) ELSE NULL END, StaffFirstID, StaffLastID, ContractorID, CustomerID, LegalPersonID, ProjectID, ProductID, ISNULL(SaleSum, 0), ISNULL(AddServiceSum, 0), ISNULL(ExternalServiceSum, 0), ISNULL(InstallemenSum, 0), ISNULL(BonusSum, 0), ISNULL(DiscountSum, 0), ISNULL(VendorDiscountSum, 0), ISNULL(ProductCostSum, 0), ISNULL(ProductCount, 0), ISNULL(ProductPrice, 0), ISNULL(ProductBasePrice, 0), ISNULL(PaymentSum, 0), ProductPriceChangeReasonID, ProductConditionID, GETDATE(), 1 FROM temp_tables.dbo.FACT_Sales_Insert
Таблица:
CREATE TABLE [dbo].[FACT_Sales]( [DateID] [int] NOT NULL, [Date] [datetime] NOT NULL, [DocType] [int] NOT NULL, [DocID] [binary](16) NOT NULL, [Number] [nvarchar](10) NULL, [ParentDocType] [int] NULL, [ParentDocID] [binary](16) NULL, [BranchID] [int] NULL, [BranchStorehouseID] [int] NULL, [BranchInstallemenID] [int] NULL, [StaffFirstID] [int] NULL, [StaffLastID] [int] NULL, [ContractorID] [int] NULL, [CustomerID] [int] NULL, [LegalPersonID] [smallint] NULL, [ProjectID] [int] NULL, [ProductID] [int] NOT NULL, [SaleSum] [numeric](15, 2) NOT NULL CONSTRAINT [DF_FACT_Sales_Sum] DEFAULT ((0)), [AddServiceSum] [numeric](15, 2) NOT NULL CONSTRAINT [DF_FACT_Sales_ServiceSum] DEFAULT ((0)), [ExternalServiceSum] [numeric](15, 2) NOT NULL CONSTRAINT [DF_FACT_Sales_ExternalServiceSum] DEFAULT ((0)), [CostSum] AS ([ProductCostSum]-[VendorDiscountSum]) PERSISTED, [MarkupSum] AS ((([SaleSum]+[AddServiceSum])-[ProductCostSum])+[VendorDiscountSum]) PERSISTED, [InstallmentSum] [numeric](15, 2) NOT NULL CONSTRAINT [DF_FACT_Sales_InstallementSum] DEFAULT ((0)), [BonusSum] [numeric](15, 2) NOT NULL CONSTRAINT [DF_FACT_Sales_BonusSum] DEFAULT ((0)), [DiscountSum] [numeric](15, 2) NOT NULL CONSTRAINT [DF_FACT_Sales_ProductDiscountSum] DEFAULT ((0)), [VendorDiscountSum] [numeric](15, 2) NOT NULL CONSTRAINT [DF_FACT_Sales_ProductVendorDiscountSum] DEFAULT ((0)), [ProductCostSum] [numeric](15, 2) NOT NULL CONSTRAINT [DF_FACT_Sales_ProductCostSum] DEFAULT ((0)), [ProductCount] [numeric](9, 0) NOT NULL CONSTRAINT [DF_FACT_Sales_ProductCount] DEFAULT ((0)), [ProductPrice] [numeric](15, 2) NOT NULL CONSTRAINT [DF_FACT_Sales_ProductPrice] DEFAULT ((0)), [ProductBasePrice] [numeric](15, 2) NOT NULL CONSTRAINT [DF_FACT_Sales_ProductBasePrice] DEFAULT ((0)), [PaymentSum] [numeric](15, 2) NOT NULL CONSTRAINT [DF_FACT_Sales_ProductPaymentSum] DEFAULT ((0)), [ProductPriceChangeReasonID] [tinyint] NULL, [ProductConditionID] [tinyint] NULL, [_DateLoad] [datetime] NULL CONSTRAINT [DF_FACT_Sales__DateLoad] DEFAULT (getdate()), [_SourceDB] [tinyint] NULL )
Таблица фактов явно связана с таблицами измерений внешними ключами (с проверкой на существование связанных элементов):
ALTER TABLE [dbo].[FACT_Sales] WITH CHECK ADD CONSTRAINT [FK_FACT_Sales_DIM_Branch] FOREIGN KEY([BranchID]) REFERENCES [dbo].[DIM_Branch] ([ID]) GO ALTER TABLE [dbo].[FACT_Sales] CHECK CONSTRAINT [FK_FACT_Sales_DIM_Branch] GO
Внешних ключей где-то 15 штук.
Всего на таблице есть 3 некластеризованных уникальных индекса и 1 кластеризованный уникальный по дате.
INSERT-ом добавляются строки за последнюю дату, в основном. Т.е., если в таблице строки до 01.07, то в insert 99% строк будет за 02.07
В таблице около 260 млн строк. Добавление 150000 строк заняло 40 минут. Другие запросы к этой таблице в это время не выполнялись.
Есть какие-либо идеи по оптимизации? Может кусочками в цикле данные добавлять? Или отсортировать их предварительно в таблице temp_tables.dbo.FACT_Sales_Insert (сейчас они расположены в произвольном порядке)?
Предварительный план insert во вложении