如何使用绑定变量转换为物化视图查询
How to convert to Materialized view query with bind variables
我的环境:
- Azure IaaS 上的 Oracle 企业版 12.2
- Linux 红帽版本 7
- 内存:32GB
- CPU : 8 vCPUs
- 内存目标设置为 16GB。
让我解释一下这个问题。我在通过 Azure Kubernetes 中的 REST 服务进行 运行 的大型查询时遇到了一些问题。该查询使用了很多表,并且在未设置绑定变量的情况下会花费很多时间。实际上,当通知绑定变量时,查询只需要 1.5 秒。我试图说服开发查询的团队强制告知参数,但他们说要求就是这样,不能挑战它。
我通过创建一些不存在的索引尽可能地改进了查询,甚至我 运行 一个 sql 调整任务来收集更多细节。我什至尝试根据 Tuning Advisor 的建议创建一个新的 sql 配置文件,但它使查询变得更慢,所以最后我放弃了它。当没有绑定值的查询单独 运行ning 时,需要 14 秒才能完成。但是,当同一查询是大规模压力测试的一部分(同时有 10 到 15 个威胁)时,一些进程因超时而死亡,以至于查询达到 60 秒而没有完成。
我一直看到相同的等待事件:PGA 内存操作(在这方面,我也尝试设置更多 PGA,我什至增加了隐藏参数 _pga_max_size
和 _smm_max_size
。我还尝试使用手动工作区设置 运行 它,我禁用了 pga_aggregated_limit
但它没有使对 运行 的查询更快或更慢。
再次澄清一下:当查询未将变量绑定到特定值时,就会出现问题。只有在这种情况下我才会遇到问题。
我最后的想法是创建一个在提交时快速刷新的物化视图。数据库上的 DML activity 很少,因此数据并发不会成为问题,我相信不会有那么多的锁定结果。我读到自 11g 以来,Oracle 在提交时的快速刷新方面有了很大改进。但是,我不知道我应该如何解决它。我应该为整个查询创建一个 MVIEW 还是应该拆分它?
我想听听您对此事的意见。或者即使您看到可以优化的内容。不要犹豫,要求任何澄清。我试图将执行计划添加到问题中,但我达到了最大正文字符数限制。
非常感谢您的支持。
查询如下:
WITH extDealer
AS (SELECT thirdPartynumber
FROM ALFAODS.ODSEXTERNALSYSTEMREFERENCE odsExt
INNER JOIN
ALFAODS.OdsThirdParty thirdParty
ON odsExt.THIRDPARTYID = thirdParty.id
WHERE odsExt.reference = :1),
selection
AS
( SELECT schedule.maturityDate,
schedule.id AS schedule_id,
schedule.alfascheduleidentifier AS scheduleId,
asset.assetidentifier AS assetId,
agreement.agreementNumber AS loanId,
proposalStatus.DETAIL AS proposalStatusCode,
schedule.scheduleStatus AS scheduleStatus,
schedule.terminationDate,
(CASE
WHEN supplier.thirdPartyNumber =
thirdPartyDealer.thirdPartyNumber
THEN
TO_CHAR (supplier.thirdPartyNumber)
ELSE
'0'
END)
AS "supplierGPNr",
(CASE
WHEN proposalStatus.DETAIL = 'RESERVED'
THEN
'0'
WHEN proposalStatus.DETAIL = 'APPROVED'
THEN
'1'
WHEN proposalStatus.DETAIL = 'FINANCED'
THEN
'2'
WHEN proposalStatus.DETAIL = 'CANCELLED'
THEN
'3'
WHEN proposalStatus.DETAIL = 'PRECANCELLED'
THEN
'3'
WHEN proposalStatus.DETAIL = 'CREDITNOTECANCELLED'
THEN
'3'
WHEN proposalStatus.DETAIL = 'WAITING'
THEN
'4'
ELSE
'5'
END)
AS loanState,
productId1.DETAIL AS productId1,
productId2.DETAIL AS productId2,
productId3.DETAIL AS productId3,
productId4.DETAIL AS productId4,
productId.DETAIL AS wmProductId,
asset.serialNumber AS vin,
asset.modelName AS modelName,
schedule.totalAssetCostFinanced AS loanAmount,
(CASE
WHEN schedule.capitalOutstanding IS NULL
THEN
0
WHEN schedule.scheduleStatus = 'Proposal'
THEN
(CASE
WHEN proposalStatus.DETAIL = 'WAITING' THEN 0
ELSE schedule.capitalOutstanding * (-1)
END)
ELSE
schedule.capitalOutstanding * (-1)
END)
AS balance,
thirdPartyDealer.thirdPartyNumber AS dealerGPNr,
thirdPartyDealer.name AS dealerNameShort,
TO_DATE (
CAST (
CASE
WHEN (creationDate.DATEFIELD = 0) THEN NULL
ELSE creationDate.DATEFIELD
END AS NVARCHAR2 (8)),
'yyyymmdd')
AS creationDate,
schedule.activationDate AS activationDate,
365 AS "KBSTATE",
assetValuationInp.narrative AS invoiceId,
(CASE
WHEN assetValuationInp.valuation IS NULL THEN 0
ELSE assetValuationInp.valuation
END)
AS invoiceAmount,
assetValuationInp.valueDate AS invoiceDate,
assetUsageHistory.readingValue AS kilometers,
installSchema.DETAIL AS installmentSchemaId,
installSchemaVer.DETAIL AS installmentSchemaVersion,
interestSchema.DETAIL AS interestSchemaId,
interestSchemaVer.DETAIL AS interestSchemaVersion,
SUBSTR (asset.serialNumber, -6) AS vinLast6,
stockId.DETAIL AS stockId,
deliveryLink.DETAIL AS deliveryLink,
TO_DATE (
CAST (
CASE
WHEN (deliveryDate.DATEFIELD = 0) THEN NULL
ELSE deliveryDate.DATEFIELD
END AS NVARCHAR2 (8)),
'yyyymmdd')
AS deliveryDate,
CASE
WHEN UPPER (CONCAT (submitter.thirdPartyNumber, '')) IN
('<NONE>', '', 'NULL')
THEN
0
ELSE
TO_NUMBER (submitter.thirdPartyNumber)
END
AS submitterId,
agreementAlert.dunningBlock AS dunningBlock,
odsInvoicingCompany.code AS "brandId",
odsInvoicingCompany.name AS "brand",
agrCompany.id AS "mandantId",
modelHSN.DETAIL AS hsn,
modelTSN.DETAIL AS tsn,
briefNumber.DETAIL AS documentNr,
schedule.MATURITYDATE AS finalDate
FROM ALFAODS.OdsScheduleMain schedule
INNER JOIN ALFAODS.OdsAgreement agreement
ON schedule.agreementId = agreement.id
AND agreement.productCode = 'WHS'
INNER JOIN ALFAODS.OdsAsset asset
ON asset.scheduleId = schedule.id
INNER JOIN ALFAODS.OdsThirdParty thirdPartyDealer
ON schedule.invCusId = thirdPartyDealer.id
INNER JOIN ALFAODS.OdsThirdParty submitter
ON schedule.dealerid = submitter.id
JOIN ALFAODS.OdsTmpSystemDate dates
ON 1 = 1
LEFT JOIN ALFAODS.OdsThirdParty supplier
ON supplier.id = asset.supplierId
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS installSchema
ON installSchema.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND installSchema.informationType = 'WINSS'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS interestSchema
ON interestSchema.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND interestSchema.informationType = 'WINTS'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS application
ON application.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND application.informationType = 'WAPID'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS productId1
ON productId1.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND productId1.informationType = 'WPID1'
AND (:2 IS NULL
OR productId1.DETAIL = NVL (:3, productId1.DETAIL))
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS productId2
ON productId2.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND productId2.informationType = 'WPID2'
AND (:4 IS NULL
OR productId2.DETAIL = NVL (:5, productId2.DETAIL))
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS productId3
ON productId3.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND productId3.informationType = 'WPID3'
AND (:6 IS NULL
OR productId3.DETAIL = NVL (:7, productId3.DETAIL))
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS productId4
ON productId4.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND productId4.informationType = 'WPID4'
AND (:8 IS NULL
OR productId4.DETAIL = NVL (:9, productId4.DETAIL))
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS stockID
ON stockID.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND stockID.informationType = 'WSTID'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS proposalStatus
ON proposalStatus.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND proposalStatus.informationType = 'WPRST'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS creationDate
ON creationDate.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND creationDate.informationType = 'WCRDT'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS installSchemaVer
ON installSchemaVer.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND installSchemaVer.informationType = 'WINSV'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS interestSchemaVer
ON interestSchemaVer.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND interestSchemaVer.informationType = 'WINTV'
-- LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS cancellationDate ON cancellationDate.alfaScheduleIdentifier = schedule.alfaScheduleIdentifier AND cancellationDate.informationType = 'WCD'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS deliveryLink
ON deliveryLink.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND deliveryLink.informationType = 'WDLNK'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS productId
ON productId.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND productId.informationType = 'WPRID'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS deliveryDate
ON deliveryDate.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND deliveryDate.informationType = 'WDELD'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS netting
ON netting.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND netting.informationType = 'WNETT'
LEFT JOIN ALFAODS.OdsAssetValuation assetValuationInp
ON ( assetValuationInp.assetId = asset.id
AND assetValuationInp.valueTypeCode = 'INP'
AND assetValuationInp.isCurrentForTypeAndSource = 1)
LEFT JOIN ALFAODS.OdsAssetUsageHistory assetUsageHistory
ON asset.assetidentifier = assetUsageHistory.assetId
LEFT JOIN ALFAODS.OdsAgreementAlert agreementAlert
ON agreementAlert.agreementId = agreement.id
LEFT JOIN ALFAODS.OdsCompany odsInvoicingCompany
ON odsInvoicingCompany.id = schedule.invCompanyId
LEFT JOIN ALFAODS.OdsCompany agrCompany
ON agrCompany.id = schedule.agrCompanyId
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOASSET modelHSN
ON modelHSN.assetIdentifier = asset.assetidentifier
AND modelHSN.informationType = u'MANUN'
AND modelHSN.DETAIL = NVL (:10, modelHSN.DETAIL)
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOASSET modelTSN
ON modelTSN.assetIdentifier = asset.assetidentifier
AND modelTSN.informationType = u'MODC'
AND modelTSN.DETAIL = NVL (:11, modelTSN.DETAIL)
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOASSET briefNumber
ON briefNumber.assetIdentifier = asset.assetidentifier
AND briefNumber.informationType = u'BNR'
AND briefNumber.DETAIL = NVL (:12, briefNumber.DETAIL)
WHERE (:13 IS NULL
OR SUBSTR (asset.serialNumber, -6) IN
( SELECT REGEXP_SUBSTR (NVL (:14, ''),
'[^,]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:15, ''),
'[^,]+',
1,
LEVEL)
IS NOT NULL))
AND (:16 IS NULL
OR asset.serialNumber IN
( SELECT REGEXP_SUBSTR (NVL (:17, ''),
'[^,]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:18, ''),
'[^,]+',
1,
LEVEL)
IS NOT NULL))
AND (:19 IS NULL
OR thirdPartyDealer.thirdPartyNumber IN
( SELECT REGEXP_SUBSTR (NVL (:20, ''),
'[^,]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:21, ''),
'[^,]+',
1,
LEVEL)
IS NOT NULL))
AND (:22 IS NULL
OR supplier.thirdPartyNumber IN
( SELECT REGEXP_SUBSTR (NVL (:23, ''),
'[^,]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:24, ''),
'[^,]+',
1,
LEVEL)
IS NOT NULL))
AND (:25 IS NULL
OR thirdPartyDealer.thirdPartyNumber IN
(SELECT thirdpartynumber FROM extDealer))
AND (:26 IS NULL
OR UPPER (proposalStatus.DETAIL) IN
( SELECT REGEXP_SUBSTR (NVL (:27, ''),
'[^,]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:28, ''),
'[^,]+',
1,
LEVEL)
IS NOT NULL))
AND (:29 IS NULL
OR agreement.agreementNumber IN
( SELECT REGEXP_SUBSTR (NVL (:30, ''),
'[^,]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:31, ''),
'[^,]+',
1,
LEVEL)
IS NOT NULL))
AND (:32 IS NULL OR asset.modelName LIKE '%' || :33 || '%')
AND ( :34 IS NULL
OR assetValuationInp.narrative = :35
OR stockId.DETAIL = :36)
AND (:37 IS NULL
OR productId1.DETAIL = NVL (:38, productId1.DETAIL))
AND (:39 IS NULL
OR productId2.DETAIL = NVL (:40, productId2.DETAIL))
AND (:41 IS NULL
OR productId3.DETAIL = NVL (:42, productId3.DETAIL))
AND (:43 IS NULL
OR productId4.DETAIL = NVL (:44, productId4.DETAIL))
AND ( (:45 IS NULL)
OR assetValuationInp.valueDate >=
TO_DATE (:46, 'yyyy-MM-dd'))
AND ( (:47 IS NULL)
OR assetValuationInp.valueDate <=
TO_DATE (:48, 'yyyy-MM-dd'))
AND ( (:49 IS NULL)
OR schedule.activationDate >=
TO_DATE (:50, 'yyyy-MM-dd'))
AND ( (:51 IS NULL)
OR schedule.activationDate <=
TO_DATE (:52, 'yyyy-MM-dd'))
AND (:53 IS NULL
OR modelHSN.DETAIL = NVL (:54, modelHSN.DETAIL))
AND (:55 IS NULL
OR modelTSN.DETAIL = NVL (:56, modelTSN.DETAIL))
AND (:57 IS NULL
OR briefNumber.DETAIL = NVL (:58, briefNumber.DETAIL))
AND (:59 IS NULL
OR (TO_DATE (:60, 'yyyy-MM-dd') <= schedule.MATURITYDATE))
AND (:61 IS NULL
OR (schedule.SCHEDULESTATUS = 'Live (Primary)'
AND TO_DATE (:62, 'yyyy-MM-dd') >=
schedule.MATURITYDATE
OR schedule.SCHEDULESTATUS = 'Terminated'
AND ADD_MONTHS (
TRUNC (TO_DATE (:63, 'yyyy-MM-dd'),
'MONTH'),
2) >= schedule.MATURITYDATE))
ORDER BY CASE
WHEN UPPER (:64) = 'LOANID' AND UPPER (:65) = 'ASC'
THEN
agreement.agreementNumber
END ASC,
CASE
WHEN UPPER (:66) = 'LOANID' AND UPPER (:67) <> 'ASC'
THEN
agreement.agreementNumber
END DESC,
CASE
WHEN UPPER (:68) <> 'LOANID' AND UPPER (:69) = 'ASC'
THEN
thirdPartyDealer.thirdPartyNumber
END ASC,
CASE
WHEN UPPER (:70) <> 'LOANID' AND UPPER (:71) <> 'ASC'
THEN
thirdPartyDealer.thirdPartyNumber
END DESC
OFFSET :72 ROWS FETCH NEXT :73 ROWS ONLY
),
Selection2
AS (
SELECT
LOANID,
PROPOSALSTATUSCODE,
SCHEDULESTATUS,
"supplierGPNr",
LOANSTATE,
PRODUCTID1,
PRODUCTID2,
PRODUCTID3,
PRODUCTID4,
WMPRODUCTID,
VIN,
MODELNAME,
LOANAMOUNT,
BALANCE,
DEALERGPNR,
DEALERNAMESHORT,
CREATIONDATE,
ACTIVATIONDATE,
CASE WHEN (scheduleStatus = 'Live (Primary)') THEN finalDate
ELSE (SELECT max(receivable.dueDate)
FROM ALFAODS.OdsReceivable receivable
INNER JOIN ALFAODS.OdsChargeType chargeType on receivable.recvChargeTypeId = chargeType.id AND chargeType.code = 2
WHERE receivable.scheduleId = schedule_id) END AS CANCELLATIONDATE,
KBSTATE,
DOCUMENTNR,
documentStateLoan.DETAIL as documentStateLoan,
loanDocumentLocation.DETAIL as documentLocation,
TO_DATE(CAST(CASE WHEN (loanDocumentDate.DATEFIELD = 0) THEN null
ELSE loanDocumentDate.DATEFIELD END AS NVARCHAR2(8)), 'yyyymmdd') as documentStatusDate,
typeId.DETAIL as schwackeCodes,
assetValuation.valuation as schwackeValue,
INVOICEID,
INVOICEAMOUNT,
INVOICEDATE,
KILOMETERS,
INSTALLMENTSCHEMAID,
0 AS INSTALLMENTSCHEMAVERSION,
INTERESTSCHEMAID,
0 AS INTERESTSCHEMAVERSION,
VINLAST6,
HSN,
TSN,
STOCKID,
NULL AS DELIVERYLINK,
DELIVERYDATE,
SUBMITTERID,
docRepositary.DETAIL as docRepositaryId,
DUNNINGBLOCK,
"brandId",
"brand",
"mandantId",
NULL AS vatDeduction,
NULL AS schwackeDeduction,
NULL AS ignoreRetention,
500 AS TOTAL
FROM selection sel
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS documentStateLoan ON documentStateLoan.alfaScheduleIdentifier = sel.scheduleId AND documentStateLoan.informationType = 'WDCLS' AND documentStateLoan.DETAIL= NVL(:74 , documentStateLoan.DETAIL)
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS loanDocumentDate ON loanDocumentDate.alfaScheduleIdentifier = sel.scheduleId AND loanDocumentDate.informationType = 'WCRDT'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS loanDocumentLocation ON loanDocumentLocation.alfaScheduleIdentifier = sel.scheduleId AND loanDocumentLocation.informationType = 'WLDLC' AND loanDocumentLocation.DETAIL = NVL(:75 , loanDocumentLocation.DETAIL)
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS docRepositary ON docRepositary.alfaScheduleIdentifier = sel.scheduleId AND docRepositary.informationType = 'WDRID'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOASSET typeId ON typeId.assetIdentifier = sel.assetId AND typeId.informationType = u'WTYID'
LEFT JOIN ALFAODS.OdsAssetValuation assetValuation on (
assetValuation.assetId = sel.assetId
AND assetValuation.valueTypeCode = 'TTV'
AND assetValuation.isCurrentForTypeAndSource = 1)
WHERE
(:76 IS NULL OR documentStateLoan.DETAIL = NVL(:77 ,documentStateLoan.DETAIL))
AND
(:78 IS NULL OR loanDocumentLocation.DETAIL = NVL(:79 ,loanDocumentLocation.DETAIL))
)
SELECT selection2.CANCELLATIONDATE as FINALDATE, selection2.* FROM selection2
where
scheduleStatus = 'Live (Primary)'
or (scheduleStatus = 'Terminated' and cancellationdate BETWEEN TO_DATE(NVL(:80 , '1900-01-01'), 'yyyy-MM-dd') AND TO_DATE(NVL(:81 ,'9999-12-31'), 'yyyy-MM-dd'))
因此,首先要回答您的问题——无法使用绑定变量提前实现这一点。您需要使用 bind-variable 条件中的 none 来具体化查询,并在具体化视图中提供足够的数据来评估绑定变量。
即
CREATE MATERIALIZED VIEW mat1 AS
SELECT ... all the data, no bind variables ...
并且在 运行 时间:
SELECT ... FROM mat1 WHERE ... bind variable conditions ...
您的查询有很多联接。 refresh fast on commit
物化视图可能很难。如果您有 Oracle 12.2,请查看物化视图的 ENABLE ON QUERY COMPUTATION
特性。基本上,您会定期刷新(可能每天或每隔几个小时,具体取决于数据的(不稳定)程度以及查询需要多长时间 运行),但 Oracle 仍然保证 real-time,新鲜的结果通过使用实体化视图日志中的数据补充(稍微陈旧的)实体化视图数据。
话虽如此,我暂时还不会去实体化视图。相反,我会根据不为空的条件切换到动态构建和执行查询。事实上,您对 Oracle 优化器施加了很大的压力,它基本上只有两个工具可以在这里做好工作:“NVL-OR 扩展”和 bind-aware 游标。
这两者都为 Oracle 提供了一种方法,可以根据为绑定变量给出的值制定不同的执行计划。它们是很好的功能,但我只是认为您的查询对我来说可能有点过分,我无法完全信任它们。如果存在已证明的问题,则尤其如此。
如果您动态地构建和执行查询,这很痛苦,诚然,您可以通过提交一堆更小、更集中、更容易优化的查询来简化 CBO 的工作。
当我说动态构建查询时,我的意思是这样的:
IF p_param_3rd_party_list IS NULL THEN
l_sql := l_sql || ' AND NVL(:23,''XXX'') IS NOT NULL';
l_sql := l_sql || ' AND NVL(:24,''XXX'') IS NOT NULL';
ELSE
-- I'm not bothering to convert all the single quotes to double quotes. Syntax won't
-- work, but you get the idea...
l_sql := l_sql || ' AND (supplier.thirdPartyNumber IN
( SELECT REGEXP_SUBSTR (NVL (:23, ''),
'[^,]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:24, ''),
'[^,]+',
1,
LEVEL)
IS NOT NULL))
END IF;
EXECUTE IMMEDIATE l_sql USING ... all your bind variables
出于可伸缩性的原因,即使您正在动态构建查询,仍然使用绑定变量至关重要,如上所示。
当绑定变量为 NULL 时添加虚拟条件的要点是最终查询具有相同顺序的相同绑定变量列表,而不管实际给出了哪些参数。这样,您可以使用一个 EXECUTE IMMEDIATE...USING...
命令执行它。否则,就是一个巨大的痛苦。
我的环境:
- Azure IaaS 上的 Oracle 企业版 12.2
- Linux 红帽版本 7
- 内存:32GB
- CPU : 8 vCPUs
- 内存目标设置为 16GB。
让我解释一下这个问题。我在通过 Azure Kubernetes 中的 REST 服务进行 运行 的大型查询时遇到了一些问题。该查询使用了很多表,并且在未设置绑定变量的情况下会花费很多时间。实际上,当通知绑定变量时,查询只需要 1.5 秒。我试图说服开发查询的团队强制告知参数,但他们说要求就是这样,不能挑战它。
我通过创建一些不存在的索引尽可能地改进了查询,甚至我 运行 一个 sql 调整任务来收集更多细节。我什至尝试根据 Tuning Advisor 的建议创建一个新的 sql 配置文件,但它使查询变得更慢,所以最后我放弃了它。当没有绑定值的查询单独 运行ning 时,需要 14 秒才能完成。但是,当同一查询是大规模压力测试的一部分(同时有 10 到 15 个威胁)时,一些进程因超时而死亡,以至于查询达到 60 秒而没有完成。
我一直看到相同的等待事件:PGA 内存操作(在这方面,我也尝试设置更多 PGA,我什至增加了隐藏参数 _pga_max_size
和 _smm_max_size
。我还尝试使用手动工作区设置 运行 它,我禁用了 pga_aggregated_limit
但它没有使对 运行 的查询更快或更慢。
再次澄清一下:当查询未将变量绑定到特定值时,就会出现问题。只有在这种情况下我才会遇到问题。
我最后的想法是创建一个在提交时快速刷新的物化视图。数据库上的 DML activity 很少,因此数据并发不会成为问题,我相信不会有那么多的锁定结果。我读到自 11g 以来,Oracle 在提交时的快速刷新方面有了很大改进。但是,我不知道我应该如何解决它。我应该为整个查询创建一个 MVIEW 还是应该拆分它?
我想听听您对此事的意见。或者即使您看到可以优化的内容。不要犹豫,要求任何澄清。我试图将执行计划添加到问题中,但我达到了最大正文字符数限制。
非常感谢您的支持。
查询如下:
WITH extDealer
AS (SELECT thirdPartynumber
FROM ALFAODS.ODSEXTERNALSYSTEMREFERENCE odsExt
INNER JOIN
ALFAODS.OdsThirdParty thirdParty
ON odsExt.THIRDPARTYID = thirdParty.id
WHERE odsExt.reference = :1),
selection
AS
( SELECT schedule.maturityDate,
schedule.id AS schedule_id,
schedule.alfascheduleidentifier AS scheduleId,
asset.assetidentifier AS assetId,
agreement.agreementNumber AS loanId,
proposalStatus.DETAIL AS proposalStatusCode,
schedule.scheduleStatus AS scheduleStatus,
schedule.terminationDate,
(CASE
WHEN supplier.thirdPartyNumber =
thirdPartyDealer.thirdPartyNumber
THEN
TO_CHAR (supplier.thirdPartyNumber)
ELSE
'0'
END)
AS "supplierGPNr",
(CASE
WHEN proposalStatus.DETAIL = 'RESERVED'
THEN
'0'
WHEN proposalStatus.DETAIL = 'APPROVED'
THEN
'1'
WHEN proposalStatus.DETAIL = 'FINANCED'
THEN
'2'
WHEN proposalStatus.DETAIL = 'CANCELLED'
THEN
'3'
WHEN proposalStatus.DETAIL = 'PRECANCELLED'
THEN
'3'
WHEN proposalStatus.DETAIL = 'CREDITNOTECANCELLED'
THEN
'3'
WHEN proposalStatus.DETAIL = 'WAITING'
THEN
'4'
ELSE
'5'
END)
AS loanState,
productId1.DETAIL AS productId1,
productId2.DETAIL AS productId2,
productId3.DETAIL AS productId3,
productId4.DETAIL AS productId4,
productId.DETAIL AS wmProductId,
asset.serialNumber AS vin,
asset.modelName AS modelName,
schedule.totalAssetCostFinanced AS loanAmount,
(CASE
WHEN schedule.capitalOutstanding IS NULL
THEN
0
WHEN schedule.scheduleStatus = 'Proposal'
THEN
(CASE
WHEN proposalStatus.DETAIL = 'WAITING' THEN 0
ELSE schedule.capitalOutstanding * (-1)
END)
ELSE
schedule.capitalOutstanding * (-1)
END)
AS balance,
thirdPartyDealer.thirdPartyNumber AS dealerGPNr,
thirdPartyDealer.name AS dealerNameShort,
TO_DATE (
CAST (
CASE
WHEN (creationDate.DATEFIELD = 0) THEN NULL
ELSE creationDate.DATEFIELD
END AS NVARCHAR2 (8)),
'yyyymmdd')
AS creationDate,
schedule.activationDate AS activationDate,
365 AS "KBSTATE",
assetValuationInp.narrative AS invoiceId,
(CASE
WHEN assetValuationInp.valuation IS NULL THEN 0
ELSE assetValuationInp.valuation
END)
AS invoiceAmount,
assetValuationInp.valueDate AS invoiceDate,
assetUsageHistory.readingValue AS kilometers,
installSchema.DETAIL AS installmentSchemaId,
installSchemaVer.DETAIL AS installmentSchemaVersion,
interestSchema.DETAIL AS interestSchemaId,
interestSchemaVer.DETAIL AS interestSchemaVersion,
SUBSTR (asset.serialNumber, -6) AS vinLast6,
stockId.DETAIL AS stockId,
deliveryLink.DETAIL AS deliveryLink,
TO_DATE (
CAST (
CASE
WHEN (deliveryDate.DATEFIELD = 0) THEN NULL
ELSE deliveryDate.DATEFIELD
END AS NVARCHAR2 (8)),
'yyyymmdd')
AS deliveryDate,
CASE
WHEN UPPER (CONCAT (submitter.thirdPartyNumber, '')) IN
('<NONE>', '', 'NULL')
THEN
0
ELSE
TO_NUMBER (submitter.thirdPartyNumber)
END
AS submitterId,
agreementAlert.dunningBlock AS dunningBlock,
odsInvoicingCompany.code AS "brandId",
odsInvoicingCompany.name AS "brand",
agrCompany.id AS "mandantId",
modelHSN.DETAIL AS hsn,
modelTSN.DETAIL AS tsn,
briefNumber.DETAIL AS documentNr,
schedule.MATURITYDATE AS finalDate
FROM ALFAODS.OdsScheduleMain schedule
INNER JOIN ALFAODS.OdsAgreement agreement
ON schedule.agreementId = agreement.id
AND agreement.productCode = 'WHS'
INNER JOIN ALFAODS.OdsAsset asset
ON asset.scheduleId = schedule.id
INNER JOIN ALFAODS.OdsThirdParty thirdPartyDealer
ON schedule.invCusId = thirdPartyDealer.id
INNER JOIN ALFAODS.OdsThirdParty submitter
ON schedule.dealerid = submitter.id
JOIN ALFAODS.OdsTmpSystemDate dates
ON 1 = 1
LEFT JOIN ALFAODS.OdsThirdParty supplier
ON supplier.id = asset.supplierId
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS installSchema
ON installSchema.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND installSchema.informationType = 'WINSS'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS interestSchema
ON interestSchema.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND interestSchema.informationType = 'WINTS'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS application
ON application.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND application.informationType = 'WAPID'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS productId1
ON productId1.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND productId1.informationType = 'WPID1'
AND (:2 IS NULL
OR productId1.DETAIL = NVL (:3, productId1.DETAIL))
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS productId2
ON productId2.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND productId2.informationType = 'WPID2'
AND (:4 IS NULL
OR productId2.DETAIL = NVL (:5, productId2.DETAIL))
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS productId3
ON productId3.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND productId3.informationType = 'WPID3'
AND (:6 IS NULL
OR productId3.DETAIL = NVL (:7, productId3.DETAIL))
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS productId4
ON productId4.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND productId4.informationType = 'WPID4'
AND (:8 IS NULL
OR productId4.DETAIL = NVL (:9, productId4.DETAIL))
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS stockID
ON stockID.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND stockID.informationType = 'WSTID'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS proposalStatus
ON proposalStatus.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND proposalStatus.informationType = 'WPRST'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS creationDate
ON creationDate.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND creationDate.informationType = 'WCRDT'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS installSchemaVer
ON installSchemaVer.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND installSchemaVer.informationType = 'WINSV'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS interestSchemaVer
ON interestSchemaVer.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND interestSchemaVer.informationType = 'WINTV'
-- LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS cancellationDate ON cancellationDate.alfaScheduleIdentifier = schedule.alfaScheduleIdentifier AND cancellationDate.informationType = 'WCD'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS deliveryLink
ON deliveryLink.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND deliveryLink.informationType = 'WDLNK'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS productId
ON productId.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND productId.informationType = 'WPRID'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS deliveryDate
ON deliveryDate.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND deliveryDate.informationType = 'WDELD'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS netting
ON netting.alfaScheduleIdentifier =
schedule.alfaScheduleIdentifier
AND netting.informationType = 'WNETT'
LEFT JOIN ALFAODS.OdsAssetValuation assetValuationInp
ON ( assetValuationInp.assetId = asset.id
AND assetValuationInp.valueTypeCode = 'INP'
AND assetValuationInp.isCurrentForTypeAndSource = 1)
LEFT JOIN ALFAODS.OdsAssetUsageHistory assetUsageHistory
ON asset.assetidentifier = assetUsageHistory.assetId
LEFT JOIN ALFAODS.OdsAgreementAlert agreementAlert
ON agreementAlert.agreementId = agreement.id
LEFT JOIN ALFAODS.OdsCompany odsInvoicingCompany
ON odsInvoicingCompany.id = schedule.invCompanyId
LEFT JOIN ALFAODS.OdsCompany agrCompany
ON agrCompany.id = schedule.agrCompanyId
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOASSET modelHSN
ON modelHSN.assetIdentifier = asset.assetidentifier
AND modelHSN.informationType = u'MANUN'
AND modelHSN.DETAIL = NVL (:10, modelHSN.DETAIL)
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOASSET modelTSN
ON modelTSN.assetIdentifier = asset.assetidentifier
AND modelTSN.informationType = u'MODC'
AND modelTSN.DETAIL = NVL (:11, modelTSN.DETAIL)
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOASSET briefNumber
ON briefNumber.assetIdentifier = asset.assetidentifier
AND briefNumber.informationType = u'BNR'
AND briefNumber.DETAIL = NVL (:12, briefNumber.DETAIL)
WHERE (:13 IS NULL
OR SUBSTR (asset.serialNumber, -6) IN
( SELECT REGEXP_SUBSTR (NVL (:14, ''),
'[^,]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:15, ''),
'[^,]+',
1,
LEVEL)
IS NOT NULL))
AND (:16 IS NULL
OR asset.serialNumber IN
( SELECT REGEXP_SUBSTR (NVL (:17, ''),
'[^,]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:18, ''),
'[^,]+',
1,
LEVEL)
IS NOT NULL))
AND (:19 IS NULL
OR thirdPartyDealer.thirdPartyNumber IN
( SELECT REGEXP_SUBSTR (NVL (:20, ''),
'[^,]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:21, ''),
'[^,]+',
1,
LEVEL)
IS NOT NULL))
AND (:22 IS NULL
OR supplier.thirdPartyNumber IN
( SELECT REGEXP_SUBSTR (NVL (:23, ''),
'[^,]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:24, ''),
'[^,]+',
1,
LEVEL)
IS NOT NULL))
AND (:25 IS NULL
OR thirdPartyDealer.thirdPartyNumber IN
(SELECT thirdpartynumber FROM extDealer))
AND (:26 IS NULL
OR UPPER (proposalStatus.DETAIL) IN
( SELECT REGEXP_SUBSTR (NVL (:27, ''),
'[^,]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:28, ''),
'[^,]+',
1,
LEVEL)
IS NOT NULL))
AND (:29 IS NULL
OR agreement.agreementNumber IN
( SELECT REGEXP_SUBSTR (NVL (:30, ''),
'[^,]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:31, ''),
'[^,]+',
1,
LEVEL)
IS NOT NULL))
AND (:32 IS NULL OR asset.modelName LIKE '%' || :33 || '%')
AND ( :34 IS NULL
OR assetValuationInp.narrative = :35
OR stockId.DETAIL = :36)
AND (:37 IS NULL
OR productId1.DETAIL = NVL (:38, productId1.DETAIL))
AND (:39 IS NULL
OR productId2.DETAIL = NVL (:40, productId2.DETAIL))
AND (:41 IS NULL
OR productId3.DETAIL = NVL (:42, productId3.DETAIL))
AND (:43 IS NULL
OR productId4.DETAIL = NVL (:44, productId4.DETAIL))
AND ( (:45 IS NULL)
OR assetValuationInp.valueDate >=
TO_DATE (:46, 'yyyy-MM-dd'))
AND ( (:47 IS NULL)
OR assetValuationInp.valueDate <=
TO_DATE (:48, 'yyyy-MM-dd'))
AND ( (:49 IS NULL)
OR schedule.activationDate >=
TO_DATE (:50, 'yyyy-MM-dd'))
AND ( (:51 IS NULL)
OR schedule.activationDate <=
TO_DATE (:52, 'yyyy-MM-dd'))
AND (:53 IS NULL
OR modelHSN.DETAIL = NVL (:54, modelHSN.DETAIL))
AND (:55 IS NULL
OR modelTSN.DETAIL = NVL (:56, modelTSN.DETAIL))
AND (:57 IS NULL
OR briefNumber.DETAIL = NVL (:58, briefNumber.DETAIL))
AND (:59 IS NULL
OR (TO_DATE (:60, 'yyyy-MM-dd') <= schedule.MATURITYDATE))
AND (:61 IS NULL
OR (schedule.SCHEDULESTATUS = 'Live (Primary)'
AND TO_DATE (:62, 'yyyy-MM-dd') >=
schedule.MATURITYDATE
OR schedule.SCHEDULESTATUS = 'Terminated'
AND ADD_MONTHS (
TRUNC (TO_DATE (:63, 'yyyy-MM-dd'),
'MONTH'),
2) >= schedule.MATURITYDATE))
ORDER BY CASE
WHEN UPPER (:64) = 'LOANID' AND UPPER (:65) = 'ASC'
THEN
agreement.agreementNumber
END ASC,
CASE
WHEN UPPER (:66) = 'LOANID' AND UPPER (:67) <> 'ASC'
THEN
agreement.agreementNumber
END DESC,
CASE
WHEN UPPER (:68) <> 'LOANID' AND UPPER (:69) = 'ASC'
THEN
thirdPartyDealer.thirdPartyNumber
END ASC,
CASE
WHEN UPPER (:70) <> 'LOANID' AND UPPER (:71) <> 'ASC'
THEN
thirdPartyDealer.thirdPartyNumber
END DESC
OFFSET :72 ROWS FETCH NEXT :73 ROWS ONLY
),
Selection2
AS (
SELECT
LOANID,
PROPOSALSTATUSCODE,
SCHEDULESTATUS,
"supplierGPNr",
LOANSTATE,
PRODUCTID1,
PRODUCTID2,
PRODUCTID3,
PRODUCTID4,
WMPRODUCTID,
VIN,
MODELNAME,
LOANAMOUNT,
BALANCE,
DEALERGPNR,
DEALERNAMESHORT,
CREATIONDATE,
ACTIVATIONDATE,
CASE WHEN (scheduleStatus = 'Live (Primary)') THEN finalDate
ELSE (SELECT max(receivable.dueDate)
FROM ALFAODS.OdsReceivable receivable
INNER JOIN ALFAODS.OdsChargeType chargeType on receivable.recvChargeTypeId = chargeType.id AND chargeType.code = 2
WHERE receivable.scheduleId = schedule_id) END AS CANCELLATIONDATE,
KBSTATE,
DOCUMENTNR,
documentStateLoan.DETAIL as documentStateLoan,
loanDocumentLocation.DETAIL as documentLocation,
TO_DATE(CAST(CASE WHEN (loanDocumentDate.DATEFIELD = 0) THEN null
ELSE loanDocumentDate.DATEFIELD END AS NVARCHAR2(8)), 'yyyymmdd') as documentStatusDate,
typeId.DETAIL as schwackeCodes,
assetValuation.valuation as schwackeValue,
INVOICEID,
INVOICEAMOUNT,
INVOICEDATE,
KILOMETERS,
INSTALLMENTSCHEMAID,
0 AS INSTALLMENTSCHEMAVERSION,
INTERESTSCHEMAID,
0 AS INTERESTSCHEMAVERSION,
VINLAST6,
HSN,
TSN,
STOCKID,
NULL AS DELIVERYLINK,
DELIVERYDATE,
SUBMITTERID,
docRepositary.DETAIL as docRepositaryId,
DUNNINGBLOCK,
"brandId",
"brand",
"mandantId",
NULL AS vatDeduction,
NULL AS schwackeDeduction,
NULL AS ignoreRetention,
500 AS TOTAL
FROM selection sel
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS documentStateLoan ON documentStateLoan.alfaScheduleIdentifier = sel.scheduleId AND documentStateLoan.informationType = 'WDCLS' AND documentStateLoan.DETAIL= NVL(:74 , documentStateLoan.DETAIL)
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS loanDocumentDate ON loanDocumentDate.alfaScheduleIdentifier = sel.scheduleId AND loanDocumentDate.informationType = 'WCRDT'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS loanDocumentLocation ON loanDocumentLocation.alfaScheduleIdentifier = sel.scheduleId AND loanDocumentLocation.informationType = 'WLDLC' AND loanDocumentLocation.DETAIL = NVL(:75 , loanDocumentLocation.DETAIL)
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOS docRepositary ON docRepositary.alfaScheduleIdentifier = sel.scheduleId AND docRepositary.informationType = 'WDRID'
LEFT JOIN ALFAODS.ODSTMPCURRENTMISCINFOASSET typeId ON typeId.assetIdentifier = sel.assetId AND typeId.informationType = u'WTYID'
LEFT JOIN ALFAODS.OdsAssetValuation assetValuation on (
assetValuation.assetId = sel.assetId
AND assetValuation.valueTypeCode = 'TTV'
AND assetValuation.isCurrentForTypeAndSource = 1)
WHERE
(:76 IS NULL OR documentStateLoan.DETAIL = NVL(:77 ,documentStateLoan.DETAIL))
AND
(:78 IS NULL OR loanDocumentLocation.DETAIL = NVL(:79 ,loanDocumentLocation.DETAIL))
)
SELECT selection2.CANCELLATIONDATE as FINALDATE, selection2.* FROM selection2
where
scheduleStatus = 'Live (Primary)'
or (scheduleStatus = 'Terminated' and cancellationdate BETWEEN TO_DATE(NVL(:80 , '1900-01-01'), 'yyyy-MM-dd') AND TO_DATE(NVL(:81 ,'9999-12-31'), 'yyyy-MM-dd'))
因此,首先要回答您的问题——无法使用绑定变量提前实现这一点。您需要使用 bind-variable 条件中的 none 来具体化查询,并在具体化视图中提供足够的数据来评估绑定变量。
即
CREATE MATERIALIZED VIEW mat1 AS
SELECT ... all the data, no bind variables ...
并且在 运行 时间:
SELECT ... FROM mat1 WHERE ... bind variable conditions ...
您的查询有很多联接。 refresh fast on commit
物化视图可能很难。如果您有 Oracle 12.2,请查看物化视图的 ENABLE ON QUERY COMPUTATION
特性。基本上,您会定期刷新(可能每天或每隔几个小时,具体取决于数据的(不稳定)程度以及查询需要多长时间 运行),但 Oracle 仍然保证 real-time,新鲜的结果通过使用实体化视图日志中的数据补充(稍微陈旧的)实体化视图数据。
话虽如此,我暂时还不会去实体化视图。相反,我会根据不为空的条件切换到动态构建和执行查询。事实上,您对 Oracle 优化器施加了很大的压力,它基本上只有两个工具可以在这里做好工作:“NVL-OR 扩展”和 bind-aware 游标。
这两者都为 Oracle 提供了一种方法,可以根据为绑定变量给出的值制定不同的执行计划。它们是很好的功能,但我只是认为您的查询对我来说可能有点过分,我无法完全信任它们。如果存在已证明的问题,则尤其如此。
如果您动态地构建和执行查询,这很痛苦,诚然,您可以通过提交一堆更小、更集中、更容易优化的查询来简化 CBO 的工作。
当我说动态构建查询时,我的意思是这样的:
IF p_param_3rd_party_list IS NULL THEN
l_sql := l_sql || ' AND NVL(:23,''XXX'') IS NOT NULL';
l_sql := l_sql || ' AND NVL(:24,''XXX'') IS NOT NULL';
ELSE
-- I'm not bothering to convert all the single quotes to double quotes. Syntax won't
-- work, but you get the idea...
l_sql := l_sql || ' AND (supplier.thirdPartyNumber IN
( SELECT REGEXP_SUBSTR (NVL (:23, ''),
'[^,]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:24, ''),
'[^,]+',
1,
LEVEL)
IS NOT NULL))
END IF;
EXECUTE IMMEDIATE l_sql USING ... all your bind variables
出于可伸缩性的原因,即使您正在动态构建查询,仍然使用绑定变量至关重要,如上所示。
当绑定变量为 NULL 时添加虚拟条件的要点是最终查询具有相同顺序的相同绑定变量列表,而不管实际给出了哪些参数。这样,您可以使用一个 EXECUTE IMMEDIATE...USING...
命令执行它。否则,就是一个巨大的痛苦。