SQL Server T-SQL оптимизация запросов - PullRequest
1 голос
/ 25 октября 2011

У меня есть запрос T-SQL, и я хочу сделать его быстрее.

У меня есть таблицы Entity и Address, и я хочу вернуть адрес, если почтовый адрес существует.

Иногда существует несколько адресов для любого данного объекта. Существует основной почтовый адрес tinyint, который иногда устанавливается, а иногда нет, здесь нет никаких правил, может быть 5 почтовых адресов по умолчанию со всеми установленными флагами или нет с установленным флагом.

Это работает примерно за 20 секунд для 11k строк, которые мне действительно нужны, чтобы сократить это время, кто-нибудь может помочь?

SELECT 
   e.*, addr.*
FROM 
   [Entity] e
   --Address does not always exist
   --PrimaryAddress is a Not Null TinyInt, sometimes this flag is enable twice for a given entity.
LEFT OUTER JOIN 
   [Address] addr ON addr.[EntityID] = e.[EntityID] 
   AND addr.Code = 'MAILING'        
   AND addr.[AddressID] = (
       --This remove duplicates but add's a long delay(15 seconds) to execution time.
       SELECT Top 1 a.[AddressID]
       FROM [Address] AS a
       WHERE a.Code = 'MAILING'
         AND a.[EntityID] = e.[EntityID]    
       ORDER BY a.[PrimaryAddress] DESC)

Следует также отметить, что я не могу добавить индексы к двум таблицам: (

С уважением Саймон Джексон

Ответы [ 3 ]

1 голос
/ 25 октября 2011

Вы можете прекратить использовать select *, вы дважды возвращаете идентификатор объекта, что приводит к расточительству как сервера, так и сетевых ресурсов. И действительно ли вам нужны все остальные поля? Устраните все, что вам не нужно. Выбор * не должен использоваться в производственном коде в любом случае.

У вас есть коррелированный подзапрос, который запускает строку путем агонизации строки, попробуйте вместо этого использовать соединения:

SELECT     e.*, addr.* 
FROM     [Entity] e     
LEFT JOIN   (SELECT addr.* 
            FROM  [Address] a
            JOIN     
                (SELECT Top 1 a.[AddressID]        
                FROM [Address] AS a        
                WHERE a.Code = 'MAILING'          
                AND a.[EntityID] = e.[EntityID]            
                ORDER BY a.[PrimaryAddress] DESC) dedup
                    ON a.address_id = dedup.address_id) addr 
    ON addr.[EntityID] = e.[EntityID] 

И снова не используйте select *, я не знаю ваших полей, или я бы указал их выше.

Конечно, реальный способ исправить это - исправить плохо спроектированную базу данных. Он не должен разрешать более одного основного адреса (мы применяем это через триггер), тогда вам не понадобится дорогая задача удаления дубликатов. Я понимаю, что в вашем случае это невозможно, но это может заставить кого-то задуматься над их недостатком дизайна. Поскольку это сторонний продукт, я бы попросил его исправить его, чтобы разрешить только один основной адрес. В конце концов, если жалуются достаточное количество людей, они могут.

1 голос
/ 25 октября 2011

Это упрощенная версия вашего запроса, которая, я думаю, будет возвращать те же строки.(Не испытано).Я не могу сказать, будет ли это быстрее, чем ваша версия.Вы говорите мне.

SELECT 
    e.*,
    addr.*
FROM 
    [Entity] e
  OUTER APPLY (
                SELECT TOP(1) *
                FROM addr as a
                WHERE a.Code = 'MAILING'
                AND a.[EntityID] = e.[EntityID] 
                ORDER BY a.[PrimaryAddress] DESC
              ) as addr
0 голосов
/ 25 октября 2011

Если вы используете SQL Server 2005 или более позднюю версию, вы можете попробовать следующее:

WITH ranked AS (
  SELECT
    *,
    rn = ROW_NUMBER() OVER (PARTITION BY EntityID ORDER BY [PrimaryAddress] DESC)
  FROM [Address]
  WHERE Code = 'MAILING'
)
SELECT
  e.*, a.*
FROM [Entity] e
  LEFT JOIN [Address] a ON a.[EntityID] = e.[EntityID] AND a.rn = 1

Результат этого запроса будет иметь крошечное отличие от вашего: будет один дополнительный столбецrn с 1 и / или NULL с.Однако я бы не стал считать это проблемой, поскольку маскированные списки SELECT не рекомендуется использовать в производственных запросах, и если это не производственный сценарий, то вряд ли будет мешать один дополнительный столбец.

Ссылки:

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