SQL 服务器 - 优化查询

SQL Server - Optimize query

我需要使用现有的 SQL 服务器存储过程,但在我看来它根本没有优化,因为没有 where 子句需要 45 秒才能完成,而且数据量不大。

我知道任何试图帮助我的人都很难测试它,但至少给我一个改进它的想法或起点。

查询的是下一个:

DECLARE @PFK_ENTERPRISE int = 7,
        @PFK_USER int = 14118,
        @ID_REGION varchar(200) = '',
        @FK_SITE int = 0,
        @FK_MARKET int = null;

DECLARE @RETURN_TABLE TABLE
                      (
                          MARKET varchar(200),
                          NAMES varchar(200),
                          PK_IDS VARCHAR (25),
                          PFK_MARKET INT,
                          IS_ADHOC BIT
                      )

INSERT INTO @RETURN_TABLE (NAMES, PK_IDS, PFK_MARKET, IS_ADHOC, MARKET )
    SELECT DISTINCT
        CASE 
            WHEN CLIENT_LEGAL.LEGAL_NAME = CLIENT_ORIGIN.LEGAL_NAME 
                THEN CLIENT_LEGAL.LEGAL_NAME 
            ELSE CLIENT_ORIGIN.LEGAL_NAME + ' (' + CLIENT_LEGAL.LEGAL_NAME + ')' 
        END AS 'NAMES',
        CONVERT(VARCHAR(10), MARKETS_CATALOGUES.PFK_CLIENT_LEGAL) + '/' + CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN) + '/'  + CONVERT(VARCHAR(10), MARKETS_CATALOGUES.PFK_COMPANY) AS 'PK_IDS',
        USER_ACCESS_CLIENTS.PFK_MARKET, 1 as "IS_ADHOC", 
        MARKET.NAME_DESCRIPTION
    FROM        
        USER_ACCESS_CLIENTS
    INNER JOIN 
        MARKETS_CATALOGUES ON USER_ACCESS_CLIENTS.PFK_ENTERPRISE = MARKETS_CATALOGUES.PFK_ENTERPRISE
                           AND USER_ACCESS_CLIENTS.PFK_MARKET = MARKETS_CATALOGUES.PFK_MARKET 
                           AND USER_ACCESS_CLIENTS.PFK_CLIENT_LEGAL = MARKETS_CATALOGUES.PFK_CLIENT_LEGAL 
                           AND USER_ACCESS_CLIENTS.PFK_CLIENT_ORIGIN = MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN  
                           AND USER_ACCESS_CLIENTS.PFK_COMPANY = MARKETS_CATALOGUES.PFK_COMPANY
    INNER JOIN 
        CLIENTS AS CLIENT_LEGAL ON MARKETS_CATALOGUES.PFK_ENTERPRISE = CLIENT_LEGAL.PFK_ENTERPRISE 
                                AND MARKETS_CATALOGUES.PFK_COMPANY = CLIENT_LEGAL.PFK_COMPANY 
                                AND MARKETS_CATALOGUES.PFK_CLIENT_LEGAL = CLIENT_LEGAL.PK_CLIENT

    INNER JOIN 
        CLIENTS AS CLIENT_ORIGIN ON MARKETS_CATALOGUES.PFK_ENTERPRISE = CLIENT_ORIGIN.PFK_ENTERPRISE 
                                 AND MARKETS_CATALOGUES.PFK_COMPANY = CLIENT_ORIGIN.PFK_COMPANY 
                                 AND MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN = CLIENT_ORIGIN.PK_CLIENT
    INNER JOIN
        MARKET ON MARKETS_CATALOGUES.PFK_ENTERPRISE = market.PFK_ENTERPRISE
               AND MARKETS_CATALOGUES.PFK_MARKET = market.PK_MARKET
    INNER JOIN 
        CATALOGUES cat ON cat.PFK_ENTERPRISE = MARKETS_CATALOGUES.PFK_ENTERPRISE 
                       AND cat.PK_CATALOGUE = MARKETS_CATALOGUES.PFK_CATALOGUE
                       AND market.FK_SITE = cat.FK_SITE
    WHERE       
        USER_ACCESS_CLIENTS.PFK_ENTERPRISE = @PFK_ENTERPRISE
        AND USER_ACCESS_CLIENTS.PFK_USER = @PFK_USER 
        AND MARKETS_CATALOGUES.FK_CATALOGUE_SETUP > 0 
        AND MARKETS_CATALOGUES.IS_ACTIVE = 1
        AND (@FK_MARKET IS NULL OR @FK_MARKET = USER_ACCESS_CLIENTS.PFK_MARKET)
        AND FK_TYPE_CATALOGUE = 6

INSERT INTO @RETURN_TABLE (NAMES, PK_IDS, PFK_MARKET, IS_ADHOC, MARKET)
    SELECT DISTINCT
        CASE WHEN CLIENT_LEGAL.LEGAL_NAME = CLIENT_ORIGIN.LEGAL_NAME THEN CLIENT_LEGAL.LEGAL_NAME ELSE CLIENT_ORIGIN.LEGAL_NAME + ' (' + CLIENT_LEGAL.LEGAL_NAME + ')' END AS 'NAMES',
        CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_CLIENT_LEGAL) + '/' + CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN) + '/'  + CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_COMPANY) AS 'PK_IDS',
        USER_ACCESS_CLIENTS.PFK_MARKET, 0 as "IS_ADHOC", 
        MARKET.NAME_DESCRIPTION AS MARKET

FROM        USER_ACCESS_CLIENTS
            inner JOIN MARKETS_CATALOGUES
                        ON USER_ACCESS_CLIENTS.PFK_ENTERPRISE = MARKETS_CATALOGUES.PFK_ENTERPRISE AND
                        USER_ACCESS_CLIENTS.PFK_MARKET = MARKETS_CATALOGUES.PFK_MARKET AND
                        USER_ACCESS_CLIENTS.PFK_CLIENT_LEGAL = MARKETS_CATALOGUES.PFK_CLIENT_LEGAL AND
                        USER_ACCESS_CLIENTS.PFK_CLIENT_ORIGIN = MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN AND
                        USER_ACCESS_CLIENTS.PFK_COMPANY = MARKETS_CATALOGUES.PFK_COMPANY
            INNER JOIN CLIENTS AS CLIENT_LEGAL 
                        ON MARKETS_CATALOGUES.PFK_ENTERPRISE = CLIENT_LEGAL.PFK_ENTERPRISE AND
                        MARKETS_CATALOGUES.PFK_COMPANY = CLIENT_LEGAL.PFK_COMPANY AND
                        MARKETS_CATALOGUES.PFK_CLIENT_LEGAL = CLIENT_LEGAL.PK_CLIENT

            INNER JOIN CLIENTS AS CLIENT_ORIGIN ON  MARKETS_CATALOGUES.PFK_ENTERPRISE = CLIENT_ORIGIN.PFK_ENTERPRISE AND

                                            MARKETS_CATALOGUES.PFK_COMPANY = CLIENT_ORIGIN.PFK_COMPANY AND

                                            MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN = CLIENT_ORIGIN.PK_CLIENT
            
            inner join MARKET on MARKETS_CATALOGUES.PFK_ENTERPRISE = market.PFK_ENTERPRISE
                                        and MARKETS_CATALOGUES.PFK_MARKET = market.PK_MARKET

            INNER JOIN CATALOGUES cat on cat.PFK_ENTERPRISE = MARKETS_CATALOGUES.PFK_ENTERPRISE and cat.PK_CATALOGUE = MARKETS_CATALOGUES.PFK_CATALOGUE
            and market.FK_SITE = cat.FK_SITE

WHERE       USER_ACCESS_CLIENTS.PFK_ENTERPRISE = @PFK_ENTERPRISE
            AND USER_ACCESS_CLIENTS.PFK_USER = @PFK_USER 
            AND MARKETS_CATALOGUES.FK_CATALOGUE_SETUP > 0 
            AND MARKETS_CATALOGUES.IS_ACTIVE = 1
            AND (@FK_MARKET IS NULL OR @FK_MARKET = USER_ACCESS_CLIENTS.PFK_MARKET)
            AND FK_TYPE_CATALOGUE <> 6
            and CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_CLIENT_LEGAL) + '/' + CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN) + '/'  + CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_COMPANY) NOT IN (select PK_IDS from @RETURN_TABLE)

            select *
            from @RETURN_TABLE
            group by PK_IDS
            order by MARKET

并且显着减慢查询速度的行是:

and CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_CLIENT_LEGAL) + '/' + CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN) + '/'  + CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_COMPANY) NOT IN (select PK_IDS from @RETURN_TABLE)

当然是因为 NOT IN (select PK_IDS from @RETURN_TABLE) 为 select每一行,但我没有找到避免该行的方法,因为评论它会在结果 temp table.

中创建重复的记录

这只是一个针对市场 231 的过滤示例,并且评论了我所说的“违规”行,因此您对返回的数据知之甚少。

adm Promotions  ADM Promotions UK Limited                           75/75/39    231 1
adm Promotions  Branding Your POS Mexico, S.A. de C.V. / BYP (MX )  107/107/39  231 1
adm Promotions  Imagen Publicitaria Punto de Venta SA de CV (MX )   111/111/39  231 1
adm Promotions  ADM Promotions UK Limited                           75/75/39    231 0
adm Promotions  Branding Your POS Mexico, S.A. de C.V. / BYP (MX )  107/107/39  231 0
adm Promotions  Imagen Publicitaria Punto de Venta SA de CV (MX )   111/111/39  231 0

因此,如您所见,有两条记录(AD_HOC 1 和 AD_HOC 0)重复记录具有相同的 PK_IDS,但我无法肯定 AD_HOC值为1或值为0的可以跳过

不知道你是否明白,希望大家帮帮忙。

尝试 1:

在结果 tmp table select 中执行下一步可以解决我的问题,我删除了“违规”行(这使得 acceptable 计时)和然后在结果中我只保留重复值中的第一个值,但 tsql 是底层的“seqnum”,其中说明不正确。 如何解决?

SELECT 
    *, 
    ROW_NUMBER() OVER (PARTITION BY PK_IDS ORDER BY market) seqnum
FROM  
    @RETURN_TABLE 
WHERE
    seqnum = 1

对于您的 seqnum 问题,您需要使用 derived tablecte来封装查询,eg

SELECT *
FROM (
  SELECT *, 
    ROW_NUMBER() OVER (PARTITION BY PK_IDS ORDER BY market) seqnum
    FROM @RETURN_TABLE 
)t
WHERE seqnum = 1;