Reputation: 115
I have a situation where I need to write a monitoring query to run every 2 hour to raise alert when processed count becomes less than 90%.
Lets say we have a Table Incoming Message where all incoming messages are captured and another table where all processed messages are captured.
This is what I came up with, this works but I am wondering if there is better way of doing this?
SELECT (CASE WHEN PROCESSEDCOUNT <= INCOMINGCOUNT * .9
THEN 'ALERT:: Process Count ' || PROCESSEDCOUNT || ' is less than 90% of Incoming count ' || INCOMINGCOUNT || '. '
ELSE 'FINE:: Process Count ' || PROCESSEDCOUNT || ' is more than or equal to 90% of Incoming count ' || INCOMINGCOUNT || '. '
END ) as Status
from
(SELECT
(SELECT COUNT(*)
FROM INCOMING_TABLE D WHERE INSERTION_TIME > SYSDATE - (1/12)
AND EXISTS (SELECT * FROM PROCESSED_TABLE C WHERE ( D.MESSAGE_ID = C.MESSAGE_ID)
AND C.PROCESSED_TIME > SYSDATE- (1/12))) AS PROCESSEDCOUNT,
(SELECT COUNT(*) FROM INCOMING_TABLE WHERE INSERTION_TIME > SYSDATE - (1/12)) AS INCOMINGCOUNT
FROM DUAL);
Upvotes: 0
Views: 120
Reputation: 2019
You are querying the same data from INCOMING_TABLE
twice, which isn't really efficient ;-)
One possibility could be to outer join:
SELECT
CASE
WHEN COUNT(C.MESSAGE_ID) <= COUNT(*) * .9
THEN 'ALERT:: Process Count ' || COUNT(C.MESSAGE_ID) || ' is less than 90% of Incoming count ' || COUNT(*) || '. '
ELSE 'FINE:: Process Count ' || COUNT(C.MESSAGE_ID) || ' is more than or equal to 90% of Incoming count ' || COUNT(*) || '. '
END as Status
FROM INCOMING_TABLE D
LEFT OUTER JOIN PROCESSED_TABLE C
ON C.MESSAGE_ID = D.MESSAGE_ID
AND C.PROCESSED_TIME > SYSDATE- (1/12)
WHERE D.INSERTION_TIME > SYSDATE - (1/12)
/
That will work if you can be sure either zero or one record exists in PROCESSED_TABLE
for each message_id. Maybe you can add a AND C.PROCESS_TYPE = ...
or something to make that condition come true.
If you cannot guarantee that a join to PROCESSED_TABLE
returns at most one row, you can move your EXISTS
to inside a COUNT
instead of the WHERE
clause and thereby again avoid accessing INCOMING_TABLE
twice:
SELECT (CASE WHEN PROCESSEDCOUNT <= INCOMINGCOUNT * .9
THEN 'ALERT:: Process Count ' || PROCESSEDCOUNT || ' is less than 90% of Incoming count ' || INCOMINGCOUNT || '. '
ELSE 'FINE:: Process Count ' || PROCESSEDCOUNT || ' is more than or equal to 90% of Incoming count ' || INCOMINGCOUNT || '. '
END ) as Status
from
(
SELECT COUNT(*) INCOMINGCOUNT
, COUNT(
CASE
WHEN EXISTS (SELECT * FROM PROCESSED_TABLE C
WHERE D.MESSAGE_ID = C.MESSAGE_ID
AND C.PROCESSED_TIME > SYSDATE- (1/12))
THEN 1
END
) PROCESSEDCOUNT
FROM INCOMING_TABLE D
WHERE D.INSERTION_TIME > SYSDATE - (1/12)
)
/
(PS. If you are at the start of writing a lot of code to handle a messaging queue, I would also suggest like @DARK_A to look into Advanced Queues instead of building your own. There is a lot of issues you need to handle in a messaging system, so why have that trouble if you can use what Oracle has already built ;-)
Upvotes: 1