我得到的响应时间约为200毫秒。 我想更多地优化它。 我怎样才能做到这一点?
CREATE OR REPLACE
PROCEDURE GETSTORES
(
LISTOFOFFERIDS IN VARCHAR2,
REF_OFFERS OUT TYPES.OFFER_RECORD_CURSOR
)
AS
BEGIN
OPEN REF_OFFERS FOR
SELECT
/*+ PARALLEL(STORES 5) PARALLEL(MERCHANTOFFERS 5)*/
MOFF.OFFERID,
s.STOREID,
S.LAT,
s.LNG
FROM
MERCHANTOFFERS MOFF
INNER JOIN STORES s ON MOFF.STOREID =S.STOREID
WHERE
MOFF.OFFERID IN
(
SELECT
REGEXP_SUBSTR(LISTOFOFFERIDS,'[^,]+', 1, LEVEL)
FROM
DUAL CONNECT BY REGEXP_SUBSTR(LISTOFOFFERIDS, '[^,]+', 1, LEVEL) IS NOT NULL
)
;
END
GETSTORES;
我正在使用regex_substr从LISTOFOFFERIDS中的逗号分隔字符串中获取OfferID列表。 我已经在Stores表的STOREID上创建了索引,但无济于事。 如果速度更快,实现相同目标的新方法也很好。
相同的类型声明:
create or replace
PACKAGE TYPES
AS
TYPE OFFER_RECORD
IS
RECORD(
OFFER_ID MERCHANTOFFERS.OFFERID%TYPE,
STORE_ID STORES.STOREID%TYPE,
LAT STORES.LAT%TYPE,
LNG STORES.LNG%TYPE
);
TYPE OFFER_RECORD_CURSOR
IS
REF
CURSOR
RETURN OFFER_RECORD;
END
TYPES;
选择计划显示以下信息:
Plan hash value: 1501040938
-------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 276 | 67620 | 17 (12)| 00:00:01 |
|* 1 | HASH JOIN | | 276 | 67620 | 17 (12)| 00:00:01 |
| 2 | NESTED LOOPS | | | | | |
| 3 | NESTED LOOPS | | 276 | 61272 | 3 (34)| 00:00:01 |
| 4 | VIEW | VW_NSO_1 | 1 | 202 | 3 (34)| 00:00:01 |
| 5 | HASH UNIQUE | | 1 | | 3 (34)| 00:00:01 |
|* 6 | CONNECT BY WITHOUT FILTERING (UNIQUE)| | | | | |
| 7 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
|* 8 | INDEX RANGE SCAN | OFFERID_INDEX | 276 | | 0 (0)| 00:00:01 |
| 9 | TABLE ACCESS BY INDEX ROWID | MERCHANTOFFERS | 276 | 5520 | 0 (0)| 00:00:01 |
| 10 | TABLE ACCESS FULL | STORES | 9947 | 223K| 13 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("MERCHANTOFFERS"."STOREID"="STORES"."STOREID")
6 - filter( REGEXP_SUBSTR ('M1-Off2,M2-Off5,M2-Off9,M5-Off4,M10-Off1,M1-Off3,M2-Off4,M3-Off2,M4-Of
f6,M5-Off1,M6-Off1,M8-Off1,M7-Off3,M1-Off1,M2-Off1,M3-Off1,M3-Off4,M3-Off5,M3-Off6,M4-Off1,M4-Off7,M2
-Off2,M3-Off3,M5-Off2,M7-Off1,M7-Off2,M1-Off7,M2-Off3,M3-Off7,M5-Off5,M4-Off2,M4-Off3,M4-Off5,M8-Off2
,M6-Off2,M1-Off5,M1-Off6,M1-Off9,M1-Off8,M2-Off6,M2-Off7,M4-Off4,M9-Off1,M6-Off4,M1-Off4,M1-Off10,M2-
Off8,M3-Off8,M6-Off3,M5-Off3','[^,]+',1,LEVEL) IS NOT NULL)
8 - access("MERCHANTOFFERS"."OFFERID"="$kkqu_col_1")
答案 0 :(得分:1)
/*+ PARALLEL(S 8) PARALLEL(MOFF 8)*/
。如果您有别名,则必须使用提示中的别名。STORES(STOREID, LAT, LNG)
)select count(distinct storeid) from (your_query)
)以及STORES表中有多少商店? (Select count(*) from Stores
)?dbms_stats.gather_table_stats
?connect by
查询不是问题。它运行0.02秒。答案 1 :(得分:0)
如果你看一下解释计划,每个步骤的时间是相同的:没有明显的候选人专注于调整。
您发布的样本有五十个代币用于OFFERID。那是代表吗?他们映射到276个商店 - 这是一个有代表性的比例?是否有任何优惠涉及多个商店?
276行约为2.7%的行,这是一个小小的条子:然而,由于STORES似乎是一个非常紧凑的表,因此索引读取是否比全表扫描更快是边缘的。
你可以做的唯一明显的事情是从数据库中挤出更多的果汁,就是在STORES(STOREID,LAT,LNG)上建立一个复合指数;大概它不是一个看到很多DML的表,所以附加索引的开销不会太大。
最后一点:您的查询以0.2秒执行。那你想要它多快多快?
答案 2 :(得分:0)
考虑在连接上删除正则表达式,因此连接可以快速发生 如果连接列上有索引,则连接可能会从嵌套循环移动 某种哈希联接。
一旦你有了结果集(希望行数减少),然后用你的正则表达式过滤它。
您可能会发现WITH语句在此场景中很有用。
有关此事的顺序。 (未经测试的例子)
WITH
base AS
(
SELECT /*+ PARALLEL(STORES 5) PARALLEL(MERCHANTOFFERS 5) */
moff.OFFERID,
s.STOREID,
s.LAT,
s.LNG
FROM MERCHANTOFFERS moff
INNER JOIN STORES s
ON MOFF.STOREID = S.STOREID
),
offers AS
(
SELECT REGEXP_SUBSTR(LISTOFOFFERIDS,'[^,]+', 1, LEVEL) offerid
FROM DUAL
CONNECT BY REGEXP_SUBSTR(LISTOFOFFERIDS, '[^,]+', 1, LEVEL) IS NOT NULL
)
SELECT base.*
FROM base,
offers
WHERE base.offerid = offers.offerid
Oracle可以将两个视图执行到内存表中,然后加入。
没有guarentees。你的milage可能会有所不同。你在寻找想法。这是一个想法。 祝你好运。
如果我正确地回忆起提示章节,当您对表名进行别名时,需要在提示中使用该别名。 / * + PARALLEL(第5条)PARALLEL(moff 5)* /
我很好奇为什么你决定为你的提示值5。我的印象是Oracle会根据系统负载和其他神秘条件选择最佳值。