Оптимизация запросов - Почему это ускоряет выполнение запроса?
-
20-09-2019 - |
Вопрос
Я использую TOAD от Quest для SQL Server на сервере SQL Server 2000.
Вот мой запрос:
SELECT CASE SLCE.GroupName WHEN 'Other' THEN ARM.FBCOMPANY
WHEN 'Inter Co.' THEN ARM.FBCOMPANY
ELSE SLCE.GroupName END AS [Company Name],
ARM.fcustno AS [Cust No],
ARM.fbcompany AS [Cust Name],
ARM.fcinvoice AS [Invoice No],
ARM.fdgldate AS [Post Date],
year(arm.fdgldate) AS [Year Posted],
CASE ARM.fcsource WHEN 'S' THEN 'Shipper'
WHEN 'O' THEN 'Sales Order'
WHEN 'R' THEN 'Receiver'
WHEN 'C' THEN 'Customer'
ELSE ARM.fcsource END AS [Source Doc Type],
CASE ARM.fcstatus WHEN 'N' THEN 'New'
WHEN 'U' THEN 'Unpaid'
WHEN 'P' THEN 'Partially Paid'
WHEN 'F' THEN 'Paid in Full'
WHEN 'H' THEN 'Held'
WHEN 'V' THEN 'Voided'
ELSE ARM.fcstatus END AS [Invoice Status],
ARM.fpono AS [Cust PO No],
ARM.fsalespn AS [Sales Person],
ARI.fitem AS [Item No],
ARI.fprodcl AS [Prod Class],
ARI.fshipkey AS [Qty Invoiced],
ARI.ftotprice AS [Net Invoiced],
ARI.fpartno AS [Part No],
ARI.frev AS [Part Rev],
cast(ARI.fmdescript AS VARCHAR(20)) AS [Part Description],
ARM.fsono AS [Sales No],
ARI.fsokey AS [SO Rels Key],
ARI.fordqty AS [Qty Ordered],
RED.[YEAR] AS [Year],
RED.PERIOD AS [RF Period]
FROM dbo.armast ARM
INNER JOIN dbo.aritem ARI
ON ARM.FCINVOICE = ARI.FCINVOICE
INNER JOIN slcdpm SLC
ON SLC.fcustno = ARM.fcustno
LEFT OUTER JOIN slcdpm_ext SLCE
ON SLC.identity_column = SLCE.fkey_id
INNER JOIN REDFRIDAYDATES..TBLREDFRIDAYALLDATES RED
ON RED.date = CAST (FLOOR (CAST (ARM.fdgldate AS FLOAT)) AS DATETIME)
WHERE ARM.fcstatus <> 'V'
AND RED.[YEAR] = year(getdate())
AND ari.frev = 'REP'
AND ARI.fsalesacc IN ('4010001', '4010002', '4010003', '4010004', '4010005', '4010006', '4010007', '4010008', '4010009', '4010010', '4010018', '4010019', '4010020', '4010021', '4010031', '4010050', '4022000', '4031000', '4045000', '4055000', '4057000', '4060000', '4070000')
Вот вариант TOAD's (с выделенными различиями) - это:
INNER JOIN dbo.aritem ARI
ON ARM.FCINVOICE = ***COALESCE (ARI.FCINVOICE , ARI.FCINVOICE)***
INNER JOIN slcdpm SLC
ON SLC.fcustno = ARM.fcustno
LEFT OUTER JOIN slcdpm_ext SLCE
ON SLC.identity_column = SLCE.fkey_id
INNER JOIN REDFRIDAYDATES..TBLREDFRIDAYALLDATES RED
ON RED.date = CAST (FLOOR (CAST (ARM.fdgldate AS FLOAT)) AS DATETIME)
WHERE ARM.fcstatus <> 'V'
AND RED.[YEAR] = year(getdate())
AND ari.frev = 'REP'
AND ARI.fsalesacc IN ('4010001', '4010002', '4010003', '4010004', '4010005', '4010006', '4010007', '4010008', '4010009', '4010010', '4010018', '4010019', '4010020', '4010021', '4010031', '4010050', '4022000', '4031000', '4045000', '4055000', '4057000', '4060000', '4070000')
***AND ARI.[fpartno] >= CHAR(0)***
Может кто-нибудь, пожалуйста, сказать мне, почему это объединение и дополнительный оператор and ускоряют этот запрос более чем на 50%?
Решение
Взглянули ли вы на Фактические Планы выполнения?Они должны показать вам различные подходы, которые применял SQL Server при выполнении этих запросов.
Другие советы
Это определенно что-то странное.План выполнения должен сказать вам наверняка, но подобные изменения производительности в базах данных почти всегда сводятся к индексу.Итак, мое лучшее предположение заключается в том, что каким-то образом sql server не хватало индекса, который он мог бы использовать, и добавление этих странных изменений сделало его лучше выделяющимся.
Но если вы хотите узнать "почему", чтобы в следующий раз, когда вы сможете написать свой запрос быстрее, в первую очередь, там действительно ничего нет.
Законченный ОСТРЯК:
Я собираюсь предположить, что в fpartno есть условие "not null" (поэтому добавленный фильтр всегда проходит), и эта жаба случайно знает, что SQLServer недостаточно умен, чтобы определить, что >=CHAR(0) всегда имеет значение true.Таким образом, это наводит на мысль, что Toad пытается очень косвенным образом направить оптимизатор на использование чего-то, в чем есть fpartno.Это что-то может быть составным индексом (fcinvoice, fpartno)..у вас есть один из таких?
Как говорили другие, план объяснения должен оказаться полезным в объяснении тайны.
Ни одно из этих изменений никак не влияет на логический смысл запроса (т. Е. это "никаких операций").
Единственным физическим эффектом ОБЪЕДИНЕНИЯ в предложении ON было бы предотвращение попыток оптимизатора использовать индекс для ARI.FCINVOICE.
Аналогично, единственный физический эффект, который ">= CHAR(0)" может оказать на оптимизатор мог бы быть, чтобы подтолкнуть его рассмотреть возможность использования сканирования индексированного диапазона (или также поиска) по индексу, в котором был ARI.[fpartno] в нем.
Итак, мой вывод заключается в том, что TOAD пытается манипулировать оптимизатором, заставляя его использовать определенный индекс, фактически не используя принуждение это использовать этот индекс с явной ПОДСКАЗКОЙ.На самом деле, это довольно умно, поскольку реальная проблема с подсказками оптимизатора T-SQL заключается в их зависимости и хрупкости.