我在Oracle Database 11g企业版11.2.0.4.0版上有这个查询 - 64位生产速度非常慢(在3.859秒内获取50行)并且我不知道还有什么办法来优化它! t_operation只有 12610行!
CREATE OR REPLACE FORCE VIEW "IOT"."V_DEVICES_LIST" ( "PRODUCT", "DEVICE_LIST") AS
select
PRODUCT ,
RTRIM(XMLAGG(XMLELEMENT(E, NAME,', ').EXTRACT('//text()') ).GetClobVal(),',') AS DEVICE_LIST
from
t_operation
where
discriminator = 'ANDROID' and product is not null
group by
PRODUCT;
EXPLAIN PLAN:
EXPLAIN PLAN
SET statement_id = 'ex_plan1' FOR
select
PRODUCT ,
RTRIM(XMLAGG(XMLELEMENT(E, NAME,', ').EXTRACT('//text()') ).GetClobVal(),',') AS DEVICE_LIST
from
t_operation
where
discriminator = 'ANDROID' and product is not null
group by
PRODUCT;
结果:
Plan hash value: 795775875
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 11484 | 246K| 11 (19)| 00:00:01 |
| 1 | SORT GROUP BY | | 11484 | 246K| 11 (19)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| T_OPERATION | 11992 | 257K| 9 (0)| 00:00:01 |
----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("PRODUCT" IS NOT NULL AND "DISCRIMINATOR"='ANDROID')
Note
-----
- Unoptimized XML construct detected (enable XMLOptimizationCheck for more information)
AND T_OPERATION:
CREATE TABLE "IOT"."T_OPERATION"
( "ID" NUMBER(38,0) NOT NULL ENABLE,
"DISCRIMINATOR" VARCHAR2(50 BYTE) NOT NULL ENABLE,
"COUNTRY" NUMBER(38,0),
"NAME" VARCHAR2(255 BYTE) NOT NULL ENABLE,
"COMPUTER" NUMBER(38,0),
"PRODUCT" NUMBER(38,0),
"ADDRESS" NUMBER(38,0),
CONSTRAINT "PK_OPR_ID" PRIMARY KEY ("ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 655360 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "IOT" ENABLE,
CONSTRAINT "FK_OPR2ADR_INF" FOREIGN KEY ("ADDRESS")
REFERENCES "IOT"."T_ADDRESS_INFO" ("ID") ENABLE,
CONSTRAINT "FK_OPR2CTR" FOREIGN KEY ("COUNTRY")
REFERENCES "IOT"."T_COUNTRY" ("ID") ENABLE,
CONSTRAINT "FK_OPR2PRD" FOREIGN KEY ("PRODUCT")
REFERENCES "IOT"."T_TABLET" ("ID") ENABLE,
CONSTRAINT "FK_OPR2SRV" FOREIGN KEY ("COMPUTER")
REFERENCES "IOT"."T_COMPUTER" ("ID") ENABLE
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS LOGGING
STORAGE(INITIAL 2097152 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "IOT" ;
CREATE INDEX "IOT"."V_DEVICES_LIST_3" ON "IOT"."T_OPERATION" (UPPER("NAME"))
PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "IOT" ;
答案 0 :(得分:1)
在discriminator
和product
列上添加索引:
create index i_operation_disc_prod on t_operation(discriminator, product);
假设discriminator='ANDROID'
产生的表格少于表格t_operation
中行数的10%。
答案 1 :(得分:1)
我认为你不能。从表中检索数据的速度尽可能快 - 因为您的过滤器似乎非常有选择性,无论如何全表扫描都可能是合适的,并且添加索引不太可能有所帮助。无论如何,这些数据量相对较快。
时间花在汇总上。我尝试使用XMLQuery而不是extract()
(因为不推荐使用),但它更慢,如果有的话。我还尝试使用用户定义的CLOB聚合器和collect()
方法(see this popular list of techniques),它们也有点慢。当然,这是我的系统和我编写的测试数据;您的结果可能会有所不同,但这些替代方案似乎不会给您带来显着的收益。
如果您的汇总名单可能超过4K - 每个产品可能只需要17个名称 - 那么您就无法使用listagg()
,并且可能是您尝试尝试的原因首先使用XMLAgg。
不幸的是,您似乎只需要承担涉及的开销,形成XMLType和CLOB操作。