A question came up on oracle-l recently about identifying which temporary segment in v$tempseg_usage is associated with which global temporary table (GTT). Here’s my answer:
v$tempseg_usage is a synonym for v$sort_usage – which is the view that I still tend to think of first – and v$sort_usage is a view over x$ktsso, and in x$ktsso the column ktssoobjn is the object number for the definition of the global temporary table (ditto for any indexes on the table). [Addendum: I didn’t point it out in the reply, but v$lock will show a TM lock with id1 set to the table object_id, and id2 set to zero, and two TO locks with the same value for id1, but with id2 set to 1 and 2 respectively.]
If an internal GTT has appeared because of subquery factoring (“with” subquery / CTE) this correspondance is a little broken but if you look in the execution plan (v$sql_plan / dbms_xplan.display_cursor()) for the query you will find lines like:
| 63 | HASH JOIN | | | 64 | VIEW | | | 65 | TABLE ACCESS FULL | SYS_TEMP_0FD9D667C_74A306D | | 66 | VIEW | | | 67 | TABLE ACCESS FULL | SYS_TEMP_0FD9D667B_74A306D |
There will be corresponding TO locks in v$lock (note the negative value):
ADDR KADDR SID TY ID1 ID2 ---------------- ---------------- ---------- -- ---------- ---------- 000000008ED8EC68 000000008ED8ECC0 143 TO -40016261 1 000000008ED8F540 000000008ED8F598 143 TO -40016260 1
And there will be some large values for ktssoobjn in x$ktsso:
KTSSOBNO KTSSOEXTS KTSSOBLKS KTSSORFNO KTSSOOBJD KTSSOOBJN KTSSOTSNUM KTSSOSQLID ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------- 49792 1 128 1 4244096 4254951035 3 anb4mscz7wz71 49152 1 128 1 4243456 4254951036 3 anb4mscz7wz71
Check the middle section of the SYS_TEMP name:
0x0FD9D667C = 4254951036
and then spot the arithmetic:
4254951036 + 40016260 = 4294967296 = 0x100000000 = power(2,32)
v$lock.id1 is a 16 bit wrap of x$ktsso.ktssoobjn, so add it to power(2,32) and you can look for it (for the relevant session) in x$ktsso.
For things like sorts we can check v$sql_workarea_active against v$sort_usage / v$tempseg_usage (though you might stick with x$ktsso to be consistent) since both hold the relative file and block number for the segment.
Follow-up
Shortly after posting a reply to the original question I received an email from Stefan Koehler pointing out that in 11.2.0.2 the object x$ktsso was enhanced to include the sql_id of the statement that caused a temporary object to come into existence. (If you check the definition of v$sort_usage/v$tempseg_usage you’ll see that the sql_id that it’s reporting is the prev_sql_id from V$session). Stefan also gave me a link to a note that he had written on the topic.
It is an oddity of v$sort_usage / v$tempseg_usage that it holds a column called session num which suggests that it ought to be the SID: it isn’t, it’s the v$session.serial#. To connect to the session information it’s probably best to join the session_addr to v$session.saddr).
(Some time later): a little oddity that I tracked down by session_addr and session_num was that an idle M001 (shared MMON slave) session was holding a (small) temporary segment long after it had last executed the statement that had allocated it. The statement in question (with a little cosmetic editing) was:
INSERT INTO WRI$_ADV_ADDM_PDBS (CON_DBID, PDB_NAME)
SELECT CON_DBID, SUBSTR(X,20)
FROM (
SELECT
I.CON_DBID,
MAX(TO_CHAR(I.OPEN_TIME, 'YYYY:MM:DD HH24:MI:SS') || I.PDB_NAME) AS X
FROM
AWR_PDB_PDB_INSTANCE I,
AWR_PDB_SNAPSHOT S
WHERE
S.DBID = :B1
AND S.INSTANCE_NUMBER = I.INSTANCE_NUMBER
AND S.SNAP_ID = :B3
AND I.STARTUP_TIME >= S.STARTUP_TIME
AND I.STARTUP_TIME <= :B2
AND I.CON_DBID <> 0
AND I.CON_DBID <> :B1
AND I.DBID = :B1
AND I.PDB_NAME IS NOT NULL
GROUP BY
I.CON_DBID
)
The SQL_ID issue is also mentioned in a comment in this article: https://jonathanlewis.wordpress.com/2014/02/16/recursive-subquery-factoring/
Comment by jkstill — March 18, 2014 @ 2:13 am GMT Mar 18,2014 |
[…] 12c the temporary undo segment is reported with segtype = “UNDEFINED” in v$sort_usage/v$tempseg_usage; by 19c this has changed to “TEMP […]
Pingback by 12c Temporary | Oracle Scratchpad — February 26, 2021 @ 11:28 am GMT Feb 26,2021 |
Jonathan,
This is only to point out that from now on (probably starting with version 11g) the missing information about the sql_id at the origin of the TEMP is visible via the column SQL_ID_TEMPSEG
But, unfortunately, the sql_id column still (19.8) points to the LAST SQL statement executed by the session (SESSION_ADD, SESSION_NUM) which may be something that has nothing to do with the TEMP.
Also, this week I was confronted with a TEMP explosion due to the usage of a TEMPORARY LOB by sessions coming from a JAVA connection pool that do not release the TEMPORAY LOB until they are disconnected. In this case, ASH shows no TEMP consumption because the java sessions filling the TEMPORARY LOB are Idle (sql net data from client). The TEMP overconsumption is only visible via gv$tempseg_usage view where the SQL_ID_TEMPSEG = 0000000000000. Not sure how to interpret this SQL_ID_TEMPSEG in this case.
Best Regards
Mohamed Houri
Comment by hourim — September 28, 2021 @ 12:39 pm BST Sep 28,2021 |
Mohamed,
Thanks for the comment.
It’s always used to accumulate corrections and extensions to the notes – especially when it’s comments about threats like your comment about temporary lobs and idle sessions in a connection pool. We always need to have alternative ways to find critical information.
I’ve got dumps of the fixed view definitions from various old versions or Oracle, and though the relevant column appeared in the x$ by 11.2.0.4, I’ve just checked and found that it wasn’t exposed in the v$ in 11.2.0.4 and didn’t arrive there until 12.1.
Regards
Jonathan Lewis
Comment by Jonathan Lewis — September 28, 2021 @ 1:06 pm BST Sep 28,2021 |
Mohamed,
I have seen quite a few databases lately where the application server pools contain huge number of connection, up to 400:1 session:core average.
Just wondering if you think the number of connections is having an effect on this as well.
Jared
Comment by Jared — September 28, 2021 @ 5:13 pm BST Sep 28,2021 |
Jared,
Regarding the TEMP consumption due to the creation of TEMPORARY LOBs, the number of connected sessions is only concerned if these sessions create TEMPORARY LOBs, use them, and return to the connection pool without being disconnected. As such, they keep their CACHE_LOBS and NOCACHE_LOBS active (values >0) in v$temporary_lobs even if they are Idle. If this session is re-used and creates a new temporary lob the existing temporary lob is not reused and a new one is created and so on. The session in the pool should explicitly free the temporary lob to avoid this situation. In one of my applications, while a call to a DBMS_LOB.FREETEMPORARY was enough to free the TEMP in 12c, it looks like this is not working as expected in 19c. I am still trying to figure this out.
Best regards
Mohamed Houri
Comment by hourim — September 29, 2021 @ 8:43 am BST Sep 29,2021 |