请教一条sql语句的执行效率
SELECT wo_no
FROM permit_active_work_order_tab
WHERE ( Permit_API.Get_Permit_Type_Id(permit_seq_) IN ('aa', 'bb', 'cc') )
AND permit_seq = permit_seq_
AND SUBSTR(WORK_ORDER_CONNECTION_API.Has_Connection_Down(WO_NO),1,5)='TRUE'
ORDER BY wo_no;我在执行上述sql语句时发现效率很低
请教高手,这个原因是什么?
附函数体:Permit_API.Get_Permit_Type_Id 和 WORK_ORDER_CONNECTION_API.Has_Connection_Down
FUNCTION Get_Permit_Type_Id (
permit_seq_ IN NUMBER ) RETURN VARCHAR2
IS
temp_ PERMIT_TAB.permit_type_id%TYPE;
CURSOR get_attr IS
SELECT permit_type_id
FROM PERMIT_TAB
WHERE permit_seq = permit_seq_;
BEGIN
OPEN get_attr;
FETCH get_attr INTO temp_;
CLOSE get_attr;
RETURN temp_;
END Get_Permit_Type_Id;FUNCTION Has_Connection (
wo_no_ IN NUMBER,
conn_up_down_ IN VARCHAR2 ) RETURN VARCHAR2
IS
CURSOR C1 IS
SELECT 1
FROM WORK_ORDER_CONNECTION_TAB
WHERE wo_no = wo_no_;CURSOR C2 IS
SELECT 1
FROM WORK_ORDER_CONNECTION_TAB
WHERE connected_wo_no = wo_no_;has_connection_ NUMBER;BEGIN
has_connection_ := 0;
IF (conn_up_down_ = 'DOWNWARDS') THEN
OPEN C1;
FETCH C1 INTO has_connection_;
CLOSE C1;
IF (has_connection_ = 1) THEN
RETURN('TRUE');
ELSE
RETURN('FALSE');
END IF;
ELSIF (conn_up_down_ = 'UPWARDS') THEN
OPEN C2;
FETCH C2 INTO has_connection_;
CLOSE C2;
IF (has_connection_ = 1) THEN
RETURN('TRUE');
ELSE
RETURN('FALSE');
END IF;
ELSE
RETURN('FALSE');
END IF;
END Has_Connection;
SELECT wo_no
FROM permit_active_work_order_tab
WHERE ( Permit_API.Get_Permit_Type_Id(permit_seq_) IN ('aa', 'bb', 'cc') )
AND permit_seq = permit_seq_
AND SUBSTR(WORK_ORDER_CONNECTION_API.Has_Connection_Down(WO_NO),1,5)='TRUE'
ORDER BY wo_no;我在执行上述sql语句时发现效率很低
请教高手,这个原因是什么?
附函数体:Permit_API.Get_Permit_Type_Id 和 WORK_ORDER_CONNECTION_API.Has_Connection_Down
FUNCTION Get_Permit_Type_Id (
permit_seq_ IN NUMBER ) RETURN VARCHAR2
IS
temp_ PERMIT_TAB.permit_type_id%TYPE;
CURSOR get_attr IS
SELECT permit_type_id
FROM PERMIT_TAB
WHERE permit_seq = permit_seq_;
BEGIN
OPEN get_attr;
FETCH get_attr INTO temp_;
CLOSE get_attr;
RETURN temp_;
END Get_Permit_Type_Id;FUNCTION Has_Connection (
wo_no_ IN NUMBER,
conn_up_down_ IN VARCHAR2 ) RETURN VARCHAR2
IS
CURSOR C1 IS
SELECT 1
FROM WORK_ORDER_CONNECTION_TAB
WHERE wo_no = wo_no_;CURSOR C2 IS
SELECT 1
FROM WORK_ORDER_CONNECTION_TAB
WHERE connected_wo_no = wo_no_;has_connection_ NUMBER;BEGIN
has_connection_ := 0;
IF (conn_up_down_ = 'DOWNWARDS') THEN
OPEN C1;
FETCH C1 INTO has_connection_;
CLOSE C1;
IF (has_connection_ = 1) THEN
RETURN('TRUE');
ELSE
RETURN('FALSE');
END IF;
ELSIF (conn_up_down_ = 'UPWARDS') THEN
OPEN C2;
FETCH C2 INTO has_connection_;
CLOSE C2;
IF (has_connection_ = 1) THEN
RETURN('TRUE');
ELSE
RETURN('FALSE');
END IF;
ELSE
RETURN('FALSE');
END IF;
END Has_Connection;
SELECT wo_no
FROM permit_active_work_order_tab
WHERE
exists(SELECT t.permit_type_id
FROM PERMIT_TAB t WHERE t.permit_seq = permit_seq_ and t.permit_type_id IN ('aa', 'bb', 'cc'))
AND permit_seq = permit_seq_
AND 1 = CASE WO_NO
when 'DOWNWARDS' then
SELECT max(1)
FROM WORK_ORDER_CONNECTION_TAB
WHERE wo_no = WO_NO
and rownum = 1
when 'UPWARDS' then
SELECT max(1)
FROM WORK_ORDER_CONNECTION_TAB
WHERE connected_wo_no = wo_no_
ELSE null END
ORDER BY wo_no;
wo_no_ IN NUMBER,
conn_up_down_ IN VARCHAR2 ) RETURN VARCHAR2声明的不一致
AND SUBSTR(WORK_ORDER_CONNECTION_API.Has_Connection_Down(WO_NO),1,5)='TRUE'速度问题就不是那么明显了。是不是说明问题主要出在这个where 上?我是用oracle 的profiler做的时间测试。
wo_no_ IN NUMBER ) RETURN VARCHAR2
IS
BEGIN
RETURN Has_Connection(wo_no_,'DOWNWARDS');
END Has_Connection_Down;
SELECT wo_no
FROM permit_active_work_order_tab
WHERE
exists(SELECT t.permit_type_id
FROM PERMIT_TAB t WHERE t.permit_seq = permit_seq_ and t.permit_type_id IN ('aa', 'bb', 'cc'))
AND permit_seq = permit_seq_
AND 1 = CASE WO_NO
when 'DOWNWARDS' then
SELECT max(1)
FROM WORK_ORDER_CONNECTION_TAB
WHERE wo_no = WO_NO
and rownum = 1
when 'UPWARDS' then
SELECT max(1)
FROM WORK_ORDER_CONNECTION_TAB
WHERE connected_wo_no = wo_no_
ELSE null END
ORDER BY wo_no;
这段中的AND 1 = CASE WO_NO
when 'DOWNWARDS' then
SELECT max(1)
FROM WORK_ORDER_CONNECTION_TAB
WHERE wo_no = WO_NO
and rownum = 1
when 'UPWARDS' then
SELECT max(1)
FROM WORK_ORDER_CONNECTION_TAB
WHERE connected_wo_no = wo_no_
ELSE null END为什么要用max(1) 是否可以直接用 select 1 呢?
你可以试试,我这里没有环境,我不记得了,不过我记得用max的话没有数据会返回NULLCASE WHEN里面有个地方忘记加rownum = 1了
是否能够提高查询效率?
现在把substr改成like 然后 针对WORK_ORDER_CONNECTION_API.Has_Connection_Down(WO_NO)这个函数建立专门的索引是否就可以有效果了呢?
如果改成 like 'true%' 也许有效果
用 intstr ()>0 的写法 会好些
还是建议 把函数 提炼成 sql
自定义函数需DETERMINISTIC关键字也就是说函数返回值是确定的,简单的说,就是入参一定的情况下返回的值也是一定的。为什么要求这样?简单的说就是, oralce对这个函数的返回值和参数值做了计算,用于下次查询时候的匹配,如果入参一定的情况下函数返回的值不一定,oracle是找不到数据的。你的function查了表里面的数据,如果你那几张表数据不会变的话那没问题这个是我的理解,请高手指正你那句sql,建议把function里面的东西拿出来,function里面有两个分支,sql语句用union all在最外层实现,union all两部分的sql直接关联表速度会比较快,包括我一开始讲的方法,你可以试试那个快
FROM permit_active_work_order_tab
WHERE
exists(SELECT t.permit_type_id
FROM PERMIT_TAB t WHERE t.permit_seq = permit_seq_ and t.permit_type_id IN ('aa', 'bb', 'cc'))
AND permit_seq = permit_seq_
AND 1 = CASE WO_NO
when 'DOWNWARDS' then
SELECT max(1)
FROM WORK_ORDER_CONNECTION_TAB
WHERE wo_no = WO_NO
and rownum = 1
when 'UPWARDS' then
SELECT max(1)
FROM WORK_ORDER_CONNECTION_TAB
WHERE connected_wo_no = wo_no_
ELSE null END
ORDER BY wo_no;
关于这段语句中的case when我有些疑问:case 后面跟的wo_no是传入的参数是吧 那么when后面的条件是针对什么来说的呢?wo_no吗?
select count(*) from test1 where upper(name) = 'abc' 这种情况依然是全表查询,强制索引亦然。这样的话是因为函数是不确定的还是该查询不是基于代价的查询呢?