存储过程更新 table 列花费的时间过多
Stored procedure is taking too much time to update the table columns
我创建了一个存储过程,它花费太多时间来更新 table 的列。假设 3 小时更新 43k 条记录中的 2.5k 条记录。
所以我可以减少更新记录的时间吗?以下是我的逻辑。
procedure UPDATE_MST_INFO_BKC
(
P_SAPID IN NVARCHAR2
)
as
v_cityname varchar2(500):='';
v_neid varchar2(500):='';
v_latitude varchar2(500):='';
v_longitude varchar2(500):='';
v_structuretype varchar2(500):='';
v_jc_name varchar2(500):='';
v_jc_code varchar2(500):='';
v_company_code varchar2(500):='';
v_cnt number :=0;
begin
select count(*) into v_cnt from structure_enodeb_mapping where RJ_SAPID=P_SAPID and rownum=1;
if v_cnt > 0 then
begin
select RJ_CITY_NAME, RJ_NETWORK_ENTITY_ID,LATITUDE,LONGITUDE,RJ_STRUCTURE_TYPE,RJ_JC_NAME,RJ_JC_CODE,'6000'
into v_cityname,v_neid,v_latitude, v_longitude, v_structuretype,v_jc_name,v_jc_code,v_company_code from structure_enodeb_mapping where RJ_SAPID=P_SAPID and rownum=1;
update tbl_ipcolo_mast_info set
CITY_NAME = v_cityname,
NEID = v_neid,
FACILITY_LATITUDE = v_latitude,
FACILITY_LONGITUDE = v_longitude,
RJ_STRUCTURE_TYPE = v_structuretype,
RJ_JC_NAME = v_jc_name,
RJ_JC_CODE = v_jc_code,
COMPANY_CODE = v_company_code
where SAP_ID=P_SAPID;
end;
end if;
end UPDATE_MST_INFO_BKC;
我可以对此做哪些调整?
3 小时?那太过分了。 sap_id
列是否已编入索引?即使不是,43K 行的数据集也太小了。
你怎么称呼那个程序?它是另一个代码的一部分,也许是一些不幸的 loop
逐行执行某些操作(反过来,慢慢地执行)?
一些反对意见:
- 所有这些变量的数据类型真的是
varchar2(500)
吗?考虑声明它们,以便它们采用 table 列的数据类型,例如v_cityname structure_enodeb_mapping.rj_city_name%type;
。此外,无需明确说明它们的值为 null (:= ''
),默认情况下如此
select
检查该参数值的 table 中是否有内容的语句应该重写为使用 EXISTS
因为它应该比 rownum = 1
条件下执行得更好用过的。
- 另外,考虑使用异常处理程序(
no-data-found
如果某个 ID 没有行;too-many-rows
如果有两行或更多行)
select
将数据收集到变量中的语句具有相同的条件;您真的希望每个 ID 不止一行(作为参数传递)吗?
无论如何,整个过程的代码可以缩短为单个 update
语句:
update tbl_ipcolo_mst_info t set
(t.city_name, t.neid, ...) = (select s.rj_city_name,
s.rj_network_entity_id, ...
from structure_enodeb_mapping s
where s.rj_sapid = t.sap_id
)
where t.sap_id = p_sapid;
有什么要更新的,会的。如果没有匹配的t.sap_id
,什么也不会发生。
据我了解您的代码,它正在更新 TBL_IPCOLO_MAST_INFO
具有 SAP_ID = P_SAPID
意味着它正在更新一条记录,您必须为每条记录调用该过程。
一次调用该过程并一次性更新所有记录是一个很好的做法。 (在您的情况下,必须仅在一次调用此过程中更新 2.5k 条记录)
根据您的要求,目前,我已将过程代码更新为仅执行 MERGE 语句,这将与您问题中的多个 SQL 相同 P_SAPID
.
PROCEDURE UPDATE_MST_INFO_BKC (
P_SAPID IN NVARCHAR2
) AS
BEGIN
MERGE INTO TBL_IPCOLO_MAST_INFO I
USING (
SELECT
RJ_CITY_NAME,
RJ_NETWORK_ENTITY_ID,
LATITUDE,
LONGITUDE,
RJ_STRUCTURE_TYPE,
RJ_JC_NAME,
RJ_JC_CODE,
'6000' AS COMPANY_CODE,
RJ_SAPID
FROM
STRUCTURE_ENODEB_MAPPING
WHERE
RJ_SAPID = P_SAPID
AND ROWNUM = 1
)
O ON ( I.SAP_ID = O.RJ_SAPID )
WHEN MATCHED THEN
UPDATE SET I.CITY_NAME = O.RJ_CITY_NAME,
I.NEID = O.RJ_NETWORK_ENTITY_ID,
I.FACILITY_LATITUDE = O.LATITUDE,
I.FACILITY_LONGITUDE = O.LONGITUDE,
I.RJ_STRUCTURE_TYPE = O.RJ_STRUCTURE_TYPE,
I.RJ_JC_NAME = O.RJ_JC_NAME,
I.RJ_JC_CODE = O.RJ_JC_CODE,
I.COMPANY_CODE = O.COMPANY_CODE;
END UPDATE_MST_INFO_BKC;
干杯!!
我创建了一个存储过程,它花费太多时间来更新 table 的列。假设 3 小时更新 43k 条记录中的 2.5k 条记录。
所以我可以减少更新记录的时间吗?以下是我的逻辑。
procedure UPDATE_MST_INFO_BKC
(
P_SAPID IN NVARCHAR2
)
as
v_cityname varchar2(500):='';
v_neid varchar2(500):='';
v_latitude varchar2(500):='';
v_longitude varchar2(500):='';
v_structuretype varchar2(500):='';
v_jc_name varchar2(500):='';
v_jc_code varchar2(500):='';
v_company_code varchar2(500):='';
v_cnt number :=0;
begin
select count(*) into v_cnt from structure_enodeb_mapping where RJ_SAPID=P_SAPID and rownum=1;
if v_cnt > 0 then
begin
select RJ_CITY_NAME, RJ_NETWORK_ENTITY_ID,LATITUDE,LONGITUDE,RJ_STRUCTURE_TYPE,RJ_JC_NAME,RJ_JC_CODE,'6000'
into v_cityname,v_neid,v_latitude, v_longitude, v_structuretype,v_jc_name,v_jc_code,v_company_code from structure_enodeb_mapping where RJ_SAPID=P_SAPID and rownum=1;
update tbl_ipcolo_mast_info set
CITY_NAME = v_cityname,
NEID = v_neid,
FACILITY_LATITUDE = v_latitude,
FACILITY_LONGITUDE = v_longitude,
RJ_STRUCTURE_TYPE = v_structuretype,
RJ_JC_NAME = v_jc_name,
RJ_JC_CODE = v_jc_code,
COMPANY_CODE = v_company_code
where SAP_ID=P_SAPID;
end;
end if;
end UPDATE_MST_INFO_BKC;
我可以对此做哪些调整?
3 小时?那太过分了。 sap_id
列是否已编入索引?即使不是,43K 行的数据集也太小了。
你怎么称呼那个程序?它是另一个代码的一部分,也许是一些不幸的 loop
逐行执行某些操作(反过来,慢慢地执行)?
一些反对意见:
- 所有这些变量的数据类型真的是
varchar2(500)
吗?考虑声明它们,以便它们采用 table 列的数据类型,例如v_cityname structure_enodeb_mapping.rj_city_name%type;
。此外,无需明确说明它们的值为 null (:= ''
),默认情况下如此 select
检查该参数值的 table 中是否有内容的语句应该重写为使用EXISTS
因为它应该比rownum = 1
条件下执行得更好用过的。- 另外,考虑使用异常处理程序(
no-data-found
如果某个 ID 没有行;too-many-rows
如果有两行或更多行)
- 另外,考虑使用异常处理程序(
select
将数据收集到变量中的语句具有相同的条件;您真的希望每个 ID 不止一行(作为参数传递)吗?
无论如何,整个过程的代码可以缩短为单个 update
语句:
update tbl_ipcolo_mst_info t set
(t.city_name, t.neid, ...) = (select s.rj_city_name,
s.rj_network_entity_id, ...
from structure_enodeb_mapping s
where s.rj_sapid = t.sap_id
)
where t.sap_id = p_sapid;
有什么要更新的,会的。如果没有匹配的t.sap_id
,什么也不会发生。
据我了解您的代码,它正在更新 TBL_IPCOLO_MAST_INFO
具有 SAP_ID = P_SAPID
意味着它正在更新一条记录,您必须为每条记录调用该过程。
一次调用该过程并一次性更新所有记录是一个很好的做法。 (在您的情况下,必须仅在一次调用此过程中更新 2.5k 条记录)
根据您的要求,目前,我已将过程代码更新为仅执行 MERGE 语句,这将与您问题中的多个 SQL 相同 P_SAPID
.
PROCEDURE UPDATE_MST_INFO_BKC (
P_SAPID IN NVARCHAR2
) AS
BEGIN
MERGE INTO TBL_IPCOLO_MAST_INFO I
USING (
SELECT
RJ_CITY_NAME,
RJ_NETWORK_ENTITY_ID,
LATITUDE,
LONGITUDE,
RJ_STRUCTURE_TYPE,
RJ_JC_NAME,
RJ_JC_CODE,
'6000' AS COMPANY_CODE,
RJ_SAPID
FROM
STRUCTURE_ENODEB_MAPPING
WHERE
RJ_SAPID = P_SAPID
AND ROWNUM = 1
)
O ON ( I.SAP_ID = O.RJ_SAPID )
WHEN MATCHED THEN
UPDATE SET I.CITY_NAME = O.RJ_CITY_NAME,
I.NEID = O.RJ_NETWORK_ENTITY_ID,
I.FACILITY_LATITUDE = O.LATITUDE,
I.FACILITY_LONGITUDE = O.LONGITUDE,
I.RJ_STRUCTURE_TYPE = O.RJ_STRUCTURE_TYPE,
I.RJ_JC_NAME = O.RJ_JC_NAME,
I.RJ_JC_CODE = O.RJ_JC_CODE,
I.COMPANY_CODE = O.COMPANY_CODE;
END UPDATE_MST_INFO_BKC;
干杯!!