使用SQL检索历史可用性
我有一个历史记录表,用于存储处置性文件的可用性 该表有1000多万行使用SQL检索历史可用性,sql,oracle,Sql,Oracle,我有一个历史记录表,用于存储处置性文件的可用性 该表有1000多万行 CREATE TABLE HIST_AVAILABLE_DISP ( DISP VARCHAR2(100 BYTE), STATUS CHAR(1 BYTE), DATE_CHECK DATE ) 我有一些带有处置性的表格: CREATE TABLE DISPOSITIVE ( ID INTEGER N
CREATE TABLE HIST_AVAILABLE_DISP
(
DISP VARCHAR2(100 BYTE),
STATUS CHAR(1 BYTE),
DATE_CHECK DATE
)
我有一些带有处置性的表格:
CREATE TABLE DISPOSITIVE
(
ID INTEGER NOT NULL,
ID_TYPE INTEGER NOT NULL,
DISP VARCHAR2(100 BYTE),
........
)
我有一个例行程序来检查处置性文件是否可用。
如果可用,我将插入一行,其中DATE\u CHECK=sysdate,STATUS=1。如果不可用,我将插入一行,说明我检查了处置式,但没有得到响应a.k.a不可用,日期为sysdate,状态为0,HIST_available_DISP中的这两个语句都不可用
我需要得到所有已经超过24小时不可用的处置。
以下是我所做的:
SELECT 'Unavailable24h' type, id_type, disp
FROM (SELECT r.id_type, r.disp, MAX (h.DATE_CHECK) last_check,
last_availability, ROUND ((MAX (h.DATE_CHECK) - last_availability), 0) days_out
FROM HIST_AVAILABLE_DISP h
INNER JOIN
(SELECT disp, MAX (DATE_CHECK) last_availability
FROM HIST_AVAILABLE_DISP h
WHERE h.status = 1
GROUP BY disp) d ON (d.disp = h.disp)
INNER JOIN DISPOSITIVE r ON (h.disp = r.disp)
WHERE r.id_type IN (1, 2)
AND h.DATA > SYSDATE - 1
GROUP BY r.disp, r.id_type) t1
WHERE days_out * 24 > 24
关键是一次选择大约需要20秒。。。因为这个查询获取的是完整的表访问,正如我所说的,它有1000多万行
CREATE TABLE HIST_AVAILABLE_DISP
(
DISP VARCHAR2(100 BYTE),
STATUS CHAR(1 BYTE),
DATE_CHECK DATE
)
有没有办法进行更快的查询?
之后,我需要检查过去365天内所有处置品的可用性,一次统计不可用处置品的数量
编辑
假设我只有两个处置式A和B:
并从历史可用显示中选择*:
我的输出是:
Day count_unavailable
16/02/2016 1
17/02/2016 0
18/02/2016 1
19/02/2016 0
解释清楚:
SELECT STATEMENT ALL_ROWSCost: 16,545 Bytes: 153,66 Cardinality: 2,561
10 FILTER
9 HASH GROUP BY Cost: 16,545 Bytes: 153,66 Cardinality: 2,561
8 HASH JOIN Cost: 16,542 Bytes: 3.072.120 Cardinality: 51,202
3 VIEW USER. Cost: 9,527 Bytes: 15,929 Cardinality: 937
2 HASH GROUP BY Cost: 9,527 Bytes: 14,992 Cardinality: 937
1 TABLE ACCESS FULL TABLE USER.HIST_AVAILABLE_DISP Cost: 9,168 Bytes: 80.954.416 Cardinality: 5.059.651
7 HASH JOIN Cost: 7,014 Bytes: 2.201.686 Cardinality: 51,202
4 TABLE ACCESS FULL TABLE USER.DISPOSITIVE Cost: 7 Bytes: 24,612 Cardinality: 879
6 TABLE ACCESS BY INDEX ROWID TABLE USER.HIST_AVAILABLE_DISP Cost: 7,006 Bytes: 819,075 Cardinality: 54,605
5 INDEX RANGE SCAN INDEX USER.IDX_DATA Cost: 315 Cardinality: 54,605
谓词信息:
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROUND(MAX("H"."DATE_CHECK")-"D"."DATE_CHECK",0)*24>24)
3 - access("D"."DISP"="H"."DISP")
6 - filter(TO_NUMBER("H"."STATUS")=1)
7 - access("H"."DISP"="D"."DISP")
8 - filter("D"."KEY_TYPE"= 1 AND ("D"."ID_TYPE"=1 OR "D"."ID_TYPE"=2))
10 - access("H"."DATE_CHECK">SYSDATE@!-1)
查询-获取过去24小时内不可用的所有DISP:
查询-获取上一次不可用但发现不可用的所有DISP:
查询-检查去年的每个24小时周期:
如果要检查全天而不是24小时,请更改:
SELECT ADD_MONTHS( SYSDATE, -12 ) + LEVEL
FROM DUAL
CONNECT BY ADD_MONTHS( SYSDATE, -12 ) + LEVEL <= SYSDATE
致:
查询-获取过去24小时内不可用的所有DISP:
查询-获取上一次不可用但发现不可用的所有DISP:
查询-检查去年的每个24小时周期:
如果要检查全天而不是24小时,请更改:
SELECT ADD_MONTHS( SYSDATE, -12 ) + LEVEL
FROM DUAL
CONNECT BY ADD_MONTHS( SYSDATE, -12 ) + LEVEL <= SYSDATE
致:
基本上我必须得到maxdate\u状态检查=0-maxdate\u状态检查=1我很抱歉。。。刚刚编辑…0=不可用并已选中。。1=可用且已选中,我需要获取所有24小时以上不可用的处置。。但我认为有一个比我做的更好的解决方案..请运行EXPLAIN PLAN FOR SELECT。。。。。你的问题。。。然后从TableDBMS_XPLAN.Display中选择*。请将上次查询的结果复制为文本-而不是位图!!!并将其附加到问题中。谢谢。确切的期望输出:日dd/mm/yyyy-过去365天内每天不可用的计数显示..基本上我必须获得maxdate状态检查=0-maxdate状态检查=1我很抱歉。。。刚刚编辑…0=不可用并已选中。。1=可用且已选中,我需要获取所有24小时以上不可用的处置。。但我认为有一个比我做的更好的解决方案..请运行EXPLAIN PLAN FOR SELECT。。。。。你的问题。。。然后从TableDBMS_XPLAN.Display中选择*。请将上次查询的结果复制为文本-而不是位图!!!并将其附加到问题中。谢谢。确切的期望输出:日dd/mm/yyyy-过去365天内每天的不可用显示计数..嘿,谢谢你的回答。。。我正在运行更大的查询以查看返回的内容。。。但我需要得到所有24小时以上无法获得的处置。。。。。。我的第一次选择与您的查询有不同的值。。。。我看不出可用性状态=0和状态=1的日期之间的差异在哪里,为什么需要获得不同可用性的日期之间的差异才能知道它已不可用超过24小时?你只需要知道,在过去24小时内,它从未可用过,并且至少有一次不可用。我必须获得检查状态为0的最大日期和可用状态为1的最大日期,并检查差异是否大于24嘿,谢谢你的回答。。。我正在运行更大的查询以查看返回的内容。。。但我需要得到所有24小时以上无法获得的处置。。。。。。我的第一次选择与您的查询有不同的值。。。。我看不出可用性状态=0和状态=1的日期之间的差异在哪里,为什么需要获得不同可用性的日期之间的差异才能知道它已不可用超过24小时?您只需要知道,在过去24小时内,它从未可用,并且至少有一次不可用。我必须获取检查状态为0的最大日期和可用状态为1的最大日期,并检查差异是否大于24
SELECT COLUMN_VALUE AS Start_of_24hr_period,
d.*
FROM DISPOSITIVE d
CROSS JOIN
TABLE(
CAST(
MULTISET(
SELECT ADD_MONTHS( SYSDATE, -12 ) + LEVEL
FROM DUAL
CONNECT BY ADD_MONTHS( SYSDATE, -12 ) + LEVEL <= SYSDATE
)
AS SYS.ODCIDATELIST
)
) y
WHERE NOT EXISTS ( SELECT 'X'
FROM HIST_AVAILABLE_DISP h
WHERE STATUS = 1
AND DATE_CHECK > y.COLUMN_VALUE - 1
AND DATE_CHECK <= y.COLUMN_VALUE
AND d.DISP = h.DISP )
AND EXISTS ( SELECT 'X'
FROM HIST_AVAILABLE_DISP h
WHERE STATUS = 0
AND DATE_CHECK > y.COLUMN_VALUE - 1
AND DATE_CHECK <= y.COLUMN_VALUE
AND d.DISP = h.DISP );
SELECT ADD_MONTHS( SYSDATE, -12 ) + LEVEL
FROM DUAL
CONNECT BY ADD_MONTHS( SYSDATE, -12 ) + LEVEL <= SYSDATE
SELECT ADD_MONTHS( TRUNC( SYSDATE ) + 1, -12 ) + LEVEL
FROM DUAL
CONNECT BY ADD_MONTHS( TRUNC( SYSDATE ) + 1, -12 ) + LEVEL <= TRUNC( SYSDATE ) + 1