Под управлением Windows Server 2012, Hyper-V, SQL Server 2012 активный / пассивный отказоустойчивый кластер с двумя 8-процессорными узлами, 60 ГБ, один экземпляр, 300 баз данных.Этот запрос дает противоречивые результаты, выполняемые где-то между 10 и 30 секундами.
DECLARE @OrgID BigInt = 780246
DECLARE @ActiveOnly Bit = 0
DECLARE @RestrictToOrgID Bit = 0;
WITH og (OrgID, GroupID) AS
(
SELECT ID, ID FROM Common.com.Organizations WHERE ISNULL(ParentID, 0) <> ID
UNION ALL
SELECT o.ID, og.GroupID FROM Common.com.Organizations o JOIN og ON og.OrgID = o.ParentID
)
SELECT e.*, v.Type AS VendorType, v.F1099, v.F1099Type, v.TaxID, v.TaxPercent,
v.ContactName, v.ContactPhone, v.ContactEMail, v.DistrictWide,
a.*
FROM og
JOIN books.Organizations bo ON bo.CommonID = og.OrgID
JOIN books.Organizations po ON po.CommonID = og.GroupID
JOIN books.Entities e ON e.OrgID = po.ID
JOIN Vendors v ON v.ID = e.ID
AND (e.OrgID = bo.ID OR v.DistrictWide = 1)
LEFT JOIN Addresses a ON a.ID = e.AddressID
WHERE bo.ID = @OrgID
AND (@ActiveOnly = 0 OR e.Active = 1)
AND (@RestrictToOrgID = 0 OR e.OrgID = @OrgID)
ORDER BY e.EntityName
Замена LEFT JOIN Addresses
на JOIN Addresses
JOIN Addresses a ON a.ID = e.AddressID
WHERE bo.ID = @OrgID
AND (@ActiveOnly = 0 OR e.Active = 1)
AND (@RestrictToOrgID = 0 OR e.OrgID = @OrgID)
ORDER BY e.EntityName
или уменьшение длины столбцов, выбранных изAddresses
до менее 100 байтов
SELECT e.*, v.Type AS VendorType, v.F1099, v.F1099Type, v.TaxID, v.TaxPercent,
v.ContactName, v.ContactPhone, v.ContactEMail, v.DistrictWide,
a.Fax
сокращает время выполнения примерно до 0,5 секунд.
Кроме того, использование SELECT DISTINCT
и соединение books.Entities
с Vendors
SELECT DISTINCT e.*, v.Type AS VendorType, v.F1099, v.F1099Type, v.TaxID, v.TaxPercent,
v.ContactName, v.ContactPhone, v.ContactEMail, v.DistrictWide,
a.*
FROM og
JOIN books.Organizations bo ON bo.CommonID = og.OrgID
JOIN books.Organizations po ON po.CommonID = og.GroupID
JOIN Vendors v
JOIN books.Entities e ON v.ID = e.ID
ON e.OrgID = bo.ID OR (e.OrgID = po.ID AND v.DistrictWide = 1)
Сокращает время примерно до 0,75 секунд.
Резюме
Эти условия указывают на то, что в экземпляре SQL Server есть какое-то ограничение ресурса, которое приводит к таким ошибочным результатам, и я не знаю, как его диагностировать.Если я скопирую поврежденную базу данных на свой ноутбук с SQL Server 2012, проблема не возникает.Я могу продолжать менять SQL и надеяться на лучшее, но я бы предпочел найти более определенное решение.
Любые предложения приветствуются.
Обновление 2/27/18
В плане выполнения для неизмененного запроса в качестве проблемы показан поиск кластерного индекса по таблице адресов.
Уменьшение длины выбранных столбцов с Addresses
до менее 100 байтов
SELECT e.*, v.Type AS VendorType, v.F1099, v.F1099Type, v.TaxID, v.TaxPercent,
v.ContactName, v.ContactPhone, v.ContactEMail, v.DistrictWide,
a.Fax
заменил поиск кластеризованного индекса сканированием кластеризованного индексачтобы получить a.Fax
и Hash Match для присоединения этого значения к результатам.
Первичный ключ таблицы Addresses
создается следующим образом:
ALTER TABLE dbo.Addresses
ADD CONSTRAINT PK_Addresses PRIMARY KEY CLUSTERED (ID ASC)
WITH (PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON)
ON PRIMARY
Этот индекс дефрагментируется и оптимизируется по мере необходимости каждый день.
Пока что я не могу найти ничего полезного в том, почему поиск по кластерному индексу так много времени добавляет к запросу..