Нужна помощь советом в какую сторону нужно смотреть.
Реализовал импорт прайс-листа по продуктам указанного производителя. В начале импорта указывается производитель и выбирается Excel-файл прайс-листа этого производителя. В процессе импорта добавляются/обновляются продукты. Считывается строка из Excel-файла, проверяется наличие этого продукта в БД по артикулу и производителю, дальше в зависимости от наличия продукта выполняется либо добавление (если нет), либо обновление (если есть) продукта. Также, во время импорта происходит проверка на дубли по артикулу (коду) продукта, в конце выводиться отчет.
Попробовал дефрагментировать индексы по этому совету. С большим файлом Excel (22411 строк) импорт занял: до - 45 минут, после - 33 минуты.
Задача: максимально ускорить процесс импорта.
Я доработал функционал, чтобы получить статистику сколько сумарно времени занимает выполнение того или иного участка кода/функции, а также какой процент приходиться на этот участок кода/функции от общего времени импорта.
В результате, узкими местами оказались функции GetOffering (10 минут, 29.4 %), CheckHasDuplicate (11.5 минут, 33.6 %), которые выполняют запрос на выборку (Select query) по продукту:
[[fn]GetOffering] TotalDuration - 600573 ms, NumberOfCalls - 22409, MinDuration - 15 ms, MaxDuration - 328 ms, AverageDuration - 26.8 ms, Portion - 29.4 %
[[fn]CheckHasDuplicate] TotalDuration - 684564 ms, NumberOfCalls - 22409, MinDuration - 15 ms, MaxDuration - 328 ms, AverageDuration - 30.55 ms, Portion - 33.6 %
Portion - это процент от общего времени выполнения импорта прайса.
Вот эти запросы:
функции GetOffering
SELECT
[tbl_Offering].[ID] AS [ID],
[tbl_ProductCode].[Code] AS [ProductCode]
FROM
[dbo].[tbl_Offering] AS [tbl_Offering]
LEFT OUTER JOIN
[dbo].[tbl_ProductCode] AS [tbl_ProductCode] ON [tbl_ProductCode].[ID] = [tbl_Offering].[ProductCodeID]
WHERE([tbl_Offering].[Article] = N'20237-179' AND
[tbl_Offering].[VendorID] = '{AFF31DDE-20C5-4207-AD54-275962A4D7F8}')
Execution plan
функции CheckHasDuplicate
SELECT
[tbl_Offering].[ID] AS [ID],
[tbl_Offering].[OriginalName] AS [OriginalName],
[tbl_Offering].[VendorID] AS [VendorID],
[Vendor].[Name] AS [VendorName],
[tbl_ProductCode].[Code] AS [ProductCode],
[tbl_Offering].[Article] AS [Article]
FROM
[dbo].[tbl_Offering] AS [tbl_Offering]
LEFT OUTER JOIN
[dbo].[tbl_Account] AS [Vendor] ON [Vendor].[ID] = [tbl_Offering].[VendorID]
LEFT OUTER JOIN
[dbo].[tbl_ProductCode] AS [tbl_ProductCode] ON [tbl_ProductCode].[ID] = [tbl_Offering].[ProductCodeID]
WHERE([tbl_Offering].[Article] = N'PCM-3730I-AE')
Execution plan
Большие картинки в прикрепленном архиве execution_plan.rar.
Смотрю в сторону индексов. В таблице tbl_Offering 152773 записи. С индексами раньше особо не работал. Возможно, стоит добавить некластерный индекс по полю Article, по которому происходит фильтрация продуктов? Может, еще что-то посоветуете? Нужно ли запускать какую-то регулярную обработку индексов, чтобы их оптимизировать?
Вот SQL-код создания таблицы tbl_Offering:
/****** Object: Table [dbo].[tbl_Offering] Script Date: 05/14/2013 15:05:44 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tbl_Offering](
[ID] [uniqueidentifier] ROWGUIDCOL NOT NULL CONSTRAINT [PDFOfferingID] DEFAULT (newid()),
[CreatedOn] [datetime] NULL,
[CreatedByID] [uniqueidentifier] NULL,
[ModifiedOn] [datetime] NULL,
[ModifiedByID] [uniqueidentifier] NULL,
[Name] [nvarchar](250) NOT NULL,
[Code] [nvarchar](250) NULL,
[CurrencyID] [uniqueidentifier] NULL,
[BasicPrice] [decimal](15, 2) NULL,
[DefaultUnitID] [uniqueidentifier] NULL,
[VendorID] [uniqueidentifier] NULL,
[SupplierID] [uniqueidentifier] NULL,
[OwnerID] [uniqueidentifier] NULL,
[OfferingTypeID] [uniqueidentifier] NULL,
[URL] [nvarchar](250) NULL,
[Description] [image] NULL,
[Weight] [decimal](15, 4) NULL,
[Volume] [decimal](15, 4) NULL,
[SerialNumber] [nvarchar](50) NULL,
[OriginalCountryID] [uniqueidentifier] NULL,
[UnitDivision] [decimal](15, 4) NULL,
[IsUsed] [int] NULL,
[ProductCodeID] [uniqueidentifier] NULL,
[GuaranteePeriod] [decimal](15, 4) NULL,
[QuantityInPackage] [decimal](15, 4) NULL,
[MinRest] [decimal](15, 4) NULL,
[StatusID] [uniqueidentifier] NULL,
[OriginalName] [nvarchar](250) NULL,
[DeliveryTerm] [decimal](15, 4) NULL,
[Price1FOB] [decimal](15, 4) NULL,
[Price1DDP] [decimal](15, 4) NULL,
[VendorCurrencyID] [uniqueidentifier] NULL,
[SupplierCurrencyID] [uniqueidentifier] NULL,
[VendorSupplierConvRateID] [nvarchar](250) NULL,
[DeliveryBasisID] [nvarchar](250) NULL,
[SupplierMarkup] [decimal](15, 4) NULL,
[SupplierExtraCostsForUkraine] [decimal](15, 4) NULL,
[EndUserPriceFOB] [decimal](15, 4) NULL,
[EndUserPriceDDP] [decimal](15, 4) NULL,
[IsSpecialSupplierPrice] [int] NULL,
[Article] [nvarchar](250) NULL,
[SupplierConversionRateID] [nvarchar](250) NULL,
[IsFixedCosts] [int] NULL,
[FixedCosts] [decimal](15, 4) NULL,
[SpecialSupplierPrice] [decimal](15, 4) NULL,
[IsRequiredIncomeControl] [int] NULL,
[OrderCode] [nvarchar](250) NULL,
[Note] [nvarchar](1000) NULL,
[IsUsedInPriceListImport] [int] NULL,
[CategoryID] [uniqueidentifier] NULL,
[GnomeID] [nvarchar](250) NULL,
[IsSeparateLineMarkupInSupplie] [int] NULL,
CONSTRAINT [POfferingID] PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[tbl_Offering] WITH CHECK ADD CONSTRAINT [FK13238CategoryIDtbl_Offeri1] FOREIGN KEY([CategoryID])
REFERENCES [dbo].[tbl_OfferingCategory] ([ID])
GO
ALTER TABLE [dbo].[tbl_Offering] CHECK CONSTRAINT [FK13238CategoryIDtbl_Offeri1]
GO
ALTER TABLE [dbo].[tbl_Offering] WITH CHECK ADD CONSTRAINT [FOfferingCurrencyID] FOREIGN KEY([CurrencyID])
REFERENCES [dbo].[tbl_Currency] ([ID])
GO
ALTER TABLE [dbo].[tbl_Offering] CHECK CONSTRAINT [FOfferingCurrencyID]
GO
ALTER TABLE [dbo].[tbl_Offering] WITH CHECK ADD CONSTRAINT [FOfferingDefaultUnitID] FOREIGN KEY([DefaultUnitID])
REFERENCES [dbo].[tbl_Unit] ([ID])
GO
ALTER TABLE [dbo].[tbl_Offering] CHECK CONSTRAINT [FOfferingDefaultUnitID]
GO
ALTER TABLE [dbo].[tbl_Offering] WITH CHECK ADD CONSTRAINT [FOfferingOfferingTypeID] FOREIGN KEY([OfferingTypeID])
REFERENCES [dbo].[tbl_OfferingType] ([ID])
GO
ALTER TABLE [dbo].[tbl_Offering] CHECK CONSTRAINT [FOfferingOfferingTypeID]
GO
ALTER TABLE [dbo].[tbl_Offering] WITH CHECK ADD CONSTRAINT [FOfferingOriginalCountryID] FOREIGN KEY([OriginalCountryID])
REFERENCES [dbo].[tbl_Country] ([ID])
GO
ALTER TABLE [dbo].[tbl_Offering] CHECK CONSTRAINT [FOfferingOriginalCountryID]
GO
ALTER TABLE [dbo].[tbl_Offering] WITH CHECK ADD CONSTRAINT [FOfferingOwnerID] FOREIGN KEY([OwnerID])
REFERENCES [dbo].[tbl_Contact] ([ID])
GO
ALTER TABLE [dbo].[tbl_Offering] CHECK CONSTRAINT [FOfferingOwnerID]
GO
ALTER TABLE [dbo].[tbl_Offering] WITH CHECK ADD CONSTRAINT [FOfferingProductCodeID] FOREIGN KEY([ProductCodeID])
REFERENCES [dbo].[tbl_ProductCode] ([ID])
GO
ALTER TABLE [dbo].[tbl_Offering] CHECK CONSTRAINT [FOfferingProductCodeID]
GO
ALTER TABLE [dbo].[tbl_Offering] WITH CHECK ADD CONSTRAINT [FOfferingStatusID2] FOREIGN KEY([StatusID])
REFERENCES [dbo].[tbl_OfferingStatus] ([ID])
GO
ALTER TABLE [dbo].[tbl_Offering] CHECK CONSTRAINT [FOfferingStatusID2]
GO
ALTER TABLE [dbo].[tbl_Offering] WITH CHECK ADD CONSTRAINT [FOfferingSupplierCurrencyID2] FOREIGN KEY([SupplierCurrencyID])
REFERENCES [dbo].[tbl_Currency] ([ID])
GO
ALTER TABLE [dbo].[tbl_Offering] CHECK CONSTRAINT [FOfferingSupplierCurrencyID2]
GO
ALTER TABLE [dbo].[tbl_Offering] WITH CHECK ADD CONSTRAINT [FOfferingSupplierID] FOREIGN KEY([SupplierID])
REFERENCES [dbo].[tbl_Account] ([ID])
GO
ALTER TABLE [dbo].[tbl_Offering] CHECK CONSTRAINT [FOfferingSupplierID]
GO
ALTER TABLE [dbo].[tbl_Offering] WITH CHECK ADD CONSTRAINT [FOfferingVendorCurrencyID] FOREIGN KEY([VendorCurrencyID])
REFERENCES [dbo].[tbl_Currency] ([ID])
GO
ALTER TABLE [dbo].[tbl_Offering] CHECK CONSTRAINT [FOfferingVendorCurrencyID]
GO
ALTER TABLE [dbo].[tbl_Offering] WITH CHECK ADD CONSTRAINT [FOfferingVendorID] FOREIGN KEY([VendorID])
REFERENCES [dbo].[tbl_Account] ([ID])
GO
ALTER TABLE [dbo].[tbl_Offering] CHECK CONSTRAINT [FOfferingVendorID]