我有一个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";