Оптимизация запросов - Почему это ускоряет выполнение запроса?

StackOverflow https://stackoverflow.com/questions/1347837

Вопрос

Я использую 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 заключается в их зависимости и хрупкости.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top