Home > Mobile >  nested query with two tables take more than 20 minutes
nested query with two tables take more than 20 minutes

Time:06-17

Here is our query which took 1229.206 seconds to execute that SQL (returning 8310286 rows):

SELECT t_01.object_uid 
FROM HashTable t_01 
WHERE t_01.object_uid IN (SELECT t_02.puid  
                          FROM ObjectTable t_02 
                          WHERE (t_02.arev_category IN (48, 40)))

Plan hash value: 1560846306

------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name              | E-Rows |E-Bytes| Cost (%CPU)|
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                   |        |       |   780K(100)|
|   1 |  NESTED LOOPS SEMI                   |                   |   7764K|   244M|   780K  (1)|
|   2 |   INDEX FULL SCAN                    | PIHashTable       |   7764K|   111M|  4073   (1)|
|*  3 |   TABLE ACCESS BY INDEX ROWID BATCHED| ObjectTable       |    290M|  4986M|     1   (0)|
|*  4 |    INDEX RANGE SCAN                  | PIOBJECTTABLE     |      1 |       |     1   (0)|
------------------------------------------------------------------------------------------------

table HashTable has 51154 blocks, last analyzed 2022/04/19 with 7764715 rows
    index PIHashTable on HashTable (OBJECT_UID)  last analyzed 2022/04/19 over 7764715 rows
table ObjectTable has 3327616 blocks, last analyzed 2022/05/02 with 290473386 rows
    index PIPPOM_OBJECT on ObjectTable (PUID)  last analyzed 2022/05/02 over 290473386 rows
    

Table ObjectTable has 290 million rows and Hashtable has 7 million rows.

Any way to optimize this?

CodePudding user response:

It's most likely going to take a while to return 8M rows. You should implement paging instead of returning all of the rows at once. It looks like you're using Oracle so try this:

select *
from (
    SELECT t_01.object_uid, row_number() over(order by t_01.object_uid) r
    FROM HashTable t_01 
    WHERE t_01.object_uid IN (
        SELECT t_02.puid  FROM ObjectTable t_02 WHERE (t_02.arev_category IN (48,40))
    )
)
where r between 1 and 1000;

Then you can get rows 1 - 1000 then 1001 - 2000 and so on. This has the added benefit of using less memory and CPU on the server per query but also returning data sooner that you (or the user) can act on while additional data is loaded in the background

CodePudding user response:

If you implement this as a join and put an index on t_02.arev_category it will be very quick.

SELECT t_01.object_uid 
FROM HashTable t_01 
JOIN ObjectTable t_02 ON t_02.arev_category IN (48, 40) and t_02.puid = t_01.object_uid

If the object table can contain the same puid for both categories 40 and 48 then do it like this:

SELECT t_01.object_uid 
FROM HashTable t_01 
JOIN (SELECT DISTINCT puid
      FROM ObjectTable
      WHERE arev_category IN (48, 40)
) t_02 ON t_02.puid = t_01.object_uid
  •  Tags:  
  • sql
  • Related