Оптимизация запросов - почему это ускоряет запросы? - PullRequest
1 голос
/ 28 августа 2009

Я использую Quest TOAD для SQL Server на SQL Server 2000 Server.

Вот мой запрос:

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 (с выделенными отличиями):

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)***

Может кто-нибудь сказать мне, почему это объединение и дополнительные и операторы ускоряют этот запрос более чем на 50%?

Ответы [ 4 ]

3 голосов
/ 28 августа 2009

Вы ознакомились с фактическими планами выполнения. Они должны показать различные подходы SQL Server к выполнению этих запросов.

1 голос
/ 28 августа 2009

Ни одно из этих изменений не повлияет на логическое значение запроса (т. Е. Они "no ops")

Единственный физический эффект, который COALESCE для предложения ON будет состоять в том, чтобы не дать оптимизатору попытаться использовать индекс для ARI.FCINVOICE.

Аналогично, единственный физический эффект, который "> = CHAR (0)" может оказать на оптимизатор , может заключаться в том, чтобы подтолкнуть его к рассмотрению использования сканирования индексированного диапазона (или также поиска) индекс, в котором был ARI. [fpartno].

Таким образом, мой вывод состоит в том, что TOAD пытается манипулировать оптимизатором для использования определенного индекса без фактического принуждения использовать его с явным HINT. На самом деле, это довольно умно, поскольку реальная проблема с подсказками оптимизатора T-SQL - это их зависимость и хрупкость.

1 голос
/ 28 августа 2009

Полный WAG:

Я собираюсь догадаться, что fpartno имеет условие «не ноль» (так что добавленный фильтр всегда проходит), и что жаба знает, что SQLServer недостаточно умен, чтобы обнаружить, что> = CHAR (0) всегда правда. Таким образом, это говорит о том, что Toad очень косвенным образом пытается направить оптимизатор к использованию чего-то, что содержит fpartno. Это может быть составной индекс (fcinvoice, fpartno) .. у вас есть один из них?

Как и другие говорили, план объяснения должен помочь объяснить загадку.

1 голос
/ 28 августа 2009

Это определенно странный. План выполнения должен сказать вам наверняка, но такие изменения производительности в базах данных почти всегда сводятся к индексу. Поэтому я думаю, что серверу sql почему-то не хватало индекса, который он мог бы использовать, и добавление этих странных изменений сделало его лучше.

Но если вы хотите узнать, почему именно так, чтобы в следующий раз вы могли написать свой запрос быстрее, в первую очередь, там действительно ничего нет.

...