0

我有一个UDF,提供一堆数据。使用了几个表变量。此时,没有创建索引。

使用 testdata 的运行时间约为30 秒

仅将表变量更改为临时表(在UDF, 因为#tables是不允许的),会显着减少运行时间。大约3 秒。本文解释了这些差异,但我不明白这一点,这是造成这种性能增量的原因。

无论如何,临时表是不允许的UDF,所以我可以很容易地使用SPROC. 不幸的是我不能,因为数据的目标“容器”必须是视图或表。由于第三方限制,不可更改。( erp 系统的数据是经过预处理的,必须在表格或视图中提供,例如您可以通过select <col> from <object>.

我尝试添加一个索引来创建当前使用的表变量,但运行时间并没有减少。

任何在最后将数据放入视图时实现临时表性能的提示或技巧都值得赞赏。

SQL-Query(添加了带表变量,但无法提供演示数据):

declare  @Results TABLE
(
          "id"                  NVARCHAR( 100 )
        , "oprNum1"             INT
        , "job1Id"              NVARCHAR( 100 )
        , "job1Type"            INT
        , "oprNum2"             INT
        , "job2Id"              NVARCHAR( 100 )
        , "job2Type"            INT
        , "minimumDistance"     INT
        , "maximumDistance"     INT
        , "resourceLocked"      INT
        , "durationLocked"      INT
        , "slot1"               FLOAT
        , "slot2"               FLOAT
        , "color"               BIGINT
        , "origin"              NVARCHAR( 50 )
        , "partition"           BIGINT 
)

    DECLARE @jobs TABLE
    (  
        "rank"              INT
        , "id"              NVARCHAR( 100 )
        , "projectId"       NVARCHAR( 100 )
        , "prodId"          NVARCHAR( 20 )
        , "oprNum"          INT
        , "oprPriority"     INT
        , "jobId"           NVARCHAR( 100 )
        , "jobType"         INT
        , "overlapFactor"   FLOAT
        , "partition"       BIGINT

        , UNIQUE CLUSTERED("rank","prodId","jobid")
    );

    INSERT INTO @jobs
    SELECT
        "rank"              = RANK() OVER ( PARTITION BY job."dataAreaId", job."prodId"
                                    , CASE job."oprPriority"
                                        WHEN 0 THEN job."oprPriority" 
                                        ELSE job."oprPriority" / job."oprPriority" 
                                    END
                                ORDER BY job."rank" )
        , "id"              = job."id"
        , "projectId"       = job."projectId"
        , "prodId"          = job."prodId"
        , "oprNum"          = job."oprNum"
        , "oprPriority"     = job."oprPriority"
        , "jobId"           = job."axJobId"
        , "jobType"         = job."jobType"
        , "overlapFactor"   = job."overlapFactor"
        , "partition" = job."partition"
    FROM "dbo"."_company_job" AS job;

    INSERT INTO @Results
    (
          "id"
        , "oprNum1"
        , "job1Id"
        , "job1Type"
        , "oprNum2"
        , "job2Id"
        , "job2Type"
        , "minimumDistance"
        , "maximumDistance"
        , "resourceLocked"
        , "durationLocked"
        , "slot1"
        , "slot2"
        , "color"
        , "origin"
        , "partition"
    )
    SELECT DISTINCT     
          "id"              = Job1."id" + N'_' + Job2."id"
        , "oprNum1"         = Job1."oprNum"
        , "job1Id"          = Job1."id"
        , "job1Type"        = Job1."jobType"
        , "oprNum2"         = Job2."oprNum"
        , "job2Id"          = Job2."id"
        , "job2Type"        = Job2."jobType"
        , "minimumDistance" = 0
        , "maximumDistance" = 0
        , "resourceLocked"  = CASE Job1."oprNum" WHEN Job2."oprNum" THEN 1 ELSE 0 END
        , "durationLocked"  = 0
        , "slot1"           = Job1."OVERLAPFACTOR"
        , "slot2"           = 0.0
        , "color"           = 0x00FFFFFF
        , "origin"          = 'job'
        , "partition" = Job1."partition"
    FROM @jobs AS Job1
    INNER JOIN @jobs AS Job2
        ON 1 = 1
        AND Job2."partition" = Job1."partition"
        AND Job2."projectId"        = Job1."projectId"
        AND Job2."oprPriority"  = Job1."oprPriority"
        AND Job2."rank"         = Job1."rank" +1
        AND Job2."id"           != Job1."id"
        AND Job2.jobType        NOT IN ( 4 )
    WHERE Job1."oprPriority" = 0
        OR ( Job1."oprPriority" > 0 AND Job1."oprNum" = job2."oprNum" );

    INSERT INTO @Results
    (
          "id"
        , "oprNum1"
        , "job1Id"
        , "job1Type"
        , "oprNum2"
        , "job2Id"
        , "job2Type"
        , "minimumDistance"
        , "maximumDistance"
        , "resourceLocked"
        , "durationLocked"
        , "slot1"
        , "slot2"
        , "color"
        , "origin"
        , "partition"
    )
    SELECT
          "id"              = Job1."id" + N'_' + Job2."id"
        , "oprNum1"         = Job1."oprNum"
        , "job1Id"          = Job1."id"
        , "job1Type"        = Job1."jobType"
        , "oprNum2"         = Job2."oprNum"
        , "job2Id"          = Job2."id"
        , "job2Type"        = Job2."jobType"
        , "minimumDistance" = 0
        , "maximumDistance" = 2147483647
        , "resourceLocked"  = CASE Job1."oprNum" WHEN Job2."oprNum" THEN 1 ELSE 0 END
        , "durationLocked"  = 0
        , "slot1"           = job2."OVERLAPFACTOR"
        , "slot2"           = 0.0
        , "color"           = 0x000000FF    
        , "origin"          = 'milestone'
        , "partition"       = Job1."partition"
    FROM @jobs AS job1
    INNER JOIN @jobs AS job2
    ON 1 = 1
    AND job2."partition" = job1."partition"
    AND job2."projectId"        = job1."projectId"
        AND Job2."oprPriority"  = Job1."oprPriority"
        AND Job2."rank"         = Job1."rank" +1
        AND Job1."id"           != Job2."id"
        AND Job2.jobType        IN ( 4 );

    INSERT INTO @Results
    (
          "id"
        , "oprNum1"
        , "job1Id"
        , "job1Type"
        , "oprNum2"
        , "job2Id"
        , "job2Type"
        , "minimumDistance"
        , "maximumDistance"
        , "resourceLocked"
        , "durationLocked"
        , "slot1"
        , "slot2"
        , "color"
        , "origin"
        , "partition"
    )
    SELECT
        "id"                = CASE slot."value" 
                                WHEN 0.0
                                    THEN Job1."id" + N'_' + Job2."id"
                                ELSE Job2."id" + N'_' + Job1."id"
                            END
        , "oprNum1"         = Job1."oprNum"
        , "job1Id"          = Job1."id"
        , "job1Type"        = Job1."jobType"
        , "oprNum2"         = Job2."oprNum"
        , "job2Id"          = Job2."id"
        , "job2Type"        = Job2."jobType"
        , "minimumDistance" = 0
        , "maximumDistance" = 0
        , "resourceLocked"  = 0
        , "durationLocked"  = 0
        , "slot1"           = slot."value"
        , "slot2"           = slot."value"
        , "color"           = 0xCCCC00FF
        , "origin"          = N'job'
        , "partition" = Job1."partition"
    FROM @jobs AS Job1
    INNER JOIN @jobs AS Job2
        ON 1 = 1
        AND job2."partition" = job1."partition"
        and  job2."projectId"       = job1."projectId"
        AND job2."oprNum"       = job1."oprNum"
        AND job2."jobType"      = job1."jobType"
        AND Job2."oprPriority"  = job1."oprPriority" +1
        AND Job2."id"           != Job1."id"
    LEFT JOIN @jobs AS prevJob
        ON 1 = 1
        AND prevJob."partition" = job2."partition" 
        AND prevJob."projectId"     =   job2."projectId"
        AND prevJob."rank"          =   job2."rank" -1
        AND prevJob."oprPriority"   =   job2."oprPriority"
        AND prevJob."id"            !=  job2."id"
    INNER JOIN "dbo"."BASEENUMS" AS enums
        ON enums."NAME" = N'someName'
        AND job1."jobType" = enums."VALUEID"
    INNER JOIN ( 
        select 0.0 as "value"
        union all 
        select 1.0 
    ) as slot
        ON ( slot."value" = 0 AND ( enums."VALUE" = N'setup' OR ( enums."VALUE" = N'normal' AND prevJob."id" IS NULL ) ) )
        OR ( slot."value" = 1 AND enums."VALUE" = N'normal' );

    DECLARE @PeggingRelations TABLE
    (
            "oprNum1"               INTEGER
            , "job1Id"              NVARCHAR( 100 )
            , "job1Type"            INT
            , "oprNum2"             INTEGER
            , "job2Id"              NVARCHAR( 100 )
            , "job2Type"            INT
            , "minimumDistance"     INT
            , "maximumDistance"     INT
            , "resourceLocked"      INT
            , "durationLocked"      INT
            , "slot1"               FLOAT
            , "slot2"               FLOAT
            , "color"               INT     
            , "origin"              NVARCHAR(50)
            , "partition" BIGINT
    );

    DECLARE @MinMax TABLE
    (
          "prodId"      NVARCHAR( 20 )
        , "maxOprNum"   INT
        , "minOprNum"   INT
    );

    INSERT INTO @MinMax
    SELECT 
          "prodId"      = "prodId"
        , "maxOprNum"   = MAX( "oprNum" ) 
        , "minOprNum"   = MIN( "oprNum" ) 
    FROM
        "dbo"."_company_job"
    GROUP BY 
          "prodId";

    INSERT INTO @PeggingRelations
    SELECT DISTINCT
        "oprNum1"           = Job1."oprNum"
        , "job1Id"          = Job1."id"
        , "job1Type"        = Job1."jobType"
        , "oprNum2"         = Job2."oprNum"
        , "job2Id"          = Job2."id"
        , "job2Type"        = Job2."jobType"
        , "minimumDistance" = 0
        , "maximumDistance" = 2147483647
        , "resourceLocked"  = CASE Job1."oprNum" WHEN Job2."oprNum" THEN 1 ELSE 0 END
        , "durationLocked"  = 0
        , "slot1"           = job1."OVERLAPFACTOR"
        , "slot2"           = 0.0
        , "color"           = 0x0000FFFF    
        , "origin"          = N'workorder'
        , "partition"       = Job1."partition"
    FROM
        "dbo"."REQTRANSCOV" AS Link
    INNER merge JOIN "dbo"."REQTRANS" AS Issuer
         ON Issuer."DATAAREAID"     = Link."DATAAREAID"
         AND Issuer."PARTITION" = Link."PARTITION"  
        AND Issuer."RECID"          = Link."ISSUERECID"
    INNER JOIN "dbo"."REQTRANS" AS Receiver
         ON Receiver."DATAAREAID"   = Link."DATAAREAID"
         AND Receiver."partition" = Link."partition"
        AND Receiver."recid"        = Link."RECEIPTRECID"
    INNER JOIN @MinMax AS IssuerMinOprNum
         ON IssuerMinOprNum."PRODID"        = Issuer."REFID"
    INNER JOIN @MinMax AS ReceiverMaxOprNum
         ON ReceiverMaxOprNum."PRODID"      = Receiver."REFID"
    INNER JOIN "dbo"."_company_job" AS Job2 
         ON Job2."prodId"           = Issuer."REFID"
        AND Job2."oprNum"           = IssuerMinOprNum."minOprNum"
        AND Job2."isFirst"      = 1
        AND Job2."oprPriority"  = 0
        AND Job2."partition" = Issuer."partition"
    INNER JOIN "dbo"."_company_job" AS Job1
         ON Job1."prodId"       = Receiver."REFID"
        AND Job1."isLast"       = 1
        AND Job1."sourceTable"  = N'PRODTABLE'
        and job1."partition" = Receiver."partition"
    WHERE  
        1 = 1
        AND Issuer."REFTYPE"    IN ( 9, 12 )
        AND Receiver."REFTYPE"  IN ( 9, 12 )
        AND Link."DATAAREAID" = N'company'

    INSERT INTO @Results
    (
          "id"
        , "oprNum1"
        , "job1Id"
        , "job1Type"
        , "oprNum2"
        , "job2Id"
        , "job2Type"
        , "minimumDistance"
        , "maximumDistance"
        , "resourceLocked"
        , "durationLocked"
        , "slot1"
        , "slot2"
        , "color"
        , "origin"      
        , "partition"
    )
    SELECT
          "id"              = "job1Id" + N'_' + "job2Id"
        , "oprNum1"
        , "job1Id"  
        , "job1Type"
        , "oprNum2"
        , "job2Id"  
        , "job2Type"        
        , "minimumDistance"
        , "maximumDistance"
        , "resourceLocked"
        , "durationLocked"
        , "slot1"
        , "slot2"
        , "color"
        , "origin"
        , "partition"
    FROM
        @PeggingRelations;

    INSERT INTO @Results 
    (
          "id"
        , "oprNum1"
        , "job1Id"
        , "job1Type"
        , "oprNum2"
        , "job2Id"
        , "job2Type"
        , "minimumDistance"
        , "maximumDistance"
        , "resourceLocked"
        , "durationLocked"
        , "slot1"
        , "slot2"
        , "color"
        , "origin"
        , "partition"
    )
    SELECT
          "id"              = Job1."id" + N'_' + Job2."id"
        , "oprNum1"         = Job1."oprNum"
        , "job1Id"          = Job1."id"
        , "job1Type"        = Job1."jobType"
        , "oprNum2"         = Job2."oprNum"
        , "job2Id"          = Job2."id"
        , "job2Type"        = Job2."jobType"
        , "minimumDistance" = 0
        , "maximumDistance" = 2147483647
        , "resourceLocked"  = CASE Job1."oprNum" WHEN Job2."oprNum" THEN 1 ELSE 0 END
        , "durationLocked"  = 0
        , "slot1"           = job1."OVERLAPFACTOR"
        , "slot2"           = 0.0
        , "color"           = 0x0000FFFF    
        , "origin"          = N'workorder'
        , "partition"       = Job1."partition"
    FROM 
        "dbo"."PRODBOM" AS PB
    INNER JOIN "dbo"."_company_job" AS Job1
         ON Job1."prodId"       = PB."INVENTREFID"
         and Job1."partition" = PB."partition"
        AND Job1."isLast"       = 1
        AND Job1."sourceTable"  = N'PRODTABLE'
        AND Job1."jobType"      = 4
    INNER JOIN "dbo"."_company_job" AS Job2
         ON Job2."prodId"       = PB."PRODID"
        AND Job2."oprNum"       = PB."OPRNUM"
        AND Job2."isFirst"      = 1
        and Job2."partition" = PB."partition"
    LEFT OUTER JOIN @Results AS Rel
         ON Rel."job1Id"    = Job1."id"
        AND Rel."job2Id"    = Job2."id"
        AND Rel."slot1"     = job1."OVERLAPFACTOR"
        AND Rel."slot2"     = 0.0
        AND Rel."partition" = Job1."partition"
    WHERE 
        1 = 1
        AND PB."DATAAREAID" = N'company'
        AND PB."INVENTREFTYPE"  = 3
        AND Rel."Id" IS NULL
        AND Rel."partition" = Job1."partition";
4

0 回答 0