sql >> Databasteknik >  >> RDS >> Oracle

Finns det något sätt att förbättra en MERGE-fråga?

Om du skulle ha en massiv problem med ditt tillvägagångssätt saknar du mycket troligt ett index i kolumnen clean.id , som krävs för din strategi när MERGE använder dual som källa för varje rad.

Detta är mindre troligt när du säger id är en primär nyckel .

i princip du tänker rätt och du kommer att se utförandeplan liknande den nedan:

---------------------------------------------------------------------------------------------------
| Id  | Operation                       | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------
|   0 | MERGE STATEMENT                 |                 |       |       |     2 (100)|          |
|   1 |  MERGE                          | CLEAN           |       |       |            |          |
|   2 |   VIEW                          |                 |       |       |            |          |
|   3 |    NESTED LOOPS OUTER           |                 |     1 |    40 |     2   (0)| 00:00:01 |
|   4 |     TABLE ACCESS FULL           | DUAL            |     1 |     2 |     2   (0)| 00:00:01 |
|   5 |     VIEW                        | VW_LAT_A18161FF |     1 |    38 |     0   (0)|          |
|   6 |      TABLE ACCESS BY INDEX ROWID| CLEAN           |     1 |    38 |     0   (0)|          |
|*  7 |       INDEX UNIQUE SCAN         | CLEAN_UX1       |     1 |       |     0   (0)|          |
---------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   7 - access("CLEAN"."ID"=:ID)

Så genomförandeplanen är bra och fungerar effektivt, men den har ett problem.

Kom ihåg att du alltid använder ett index, du kommer att vara nöjd när du bearbetar några rader, men det kommer inte att skalas .

Om du bearbetar en miljoner av poster kan du falla tillbaka till en tvåstegsbearbetning,

  • infoga alla rader i en tillfällig tabell

  • utför en enda MERGE uttalande med den temporära tabellen

Den stora fördelen är att Oracle kan öppna en hash join och bli av med indexåtkomsten för var och en av miljonerna rader.

Här ett exempel på ett test av clean tabell initierad med 1M id (visas inte) och utför 1M infogning och 1M uppdateringar:

n  = 1000000
data2 = [{"id" : i, "xcount" :1} for i in range(2*n)]  

sql3 = """
    insert into tmp (id,count)
    values (:id,:xcount)"""
sql4 = """MERGE into clean USING tmp on (clean.id = tmp.id)
          when not matched then insert (id, count)  values (tmp.id, tmp.count)
          when matched then update set clean.count= clean.count + tmp.count"""    

cursor.executemany(sql3, data2)
cursor.execute(sql4)

Testet pågår i ca. 10 sekunder, vilket är mindre än hälften av dig närmar dig med MERGE med dual .

Om detta fortfarande inte räcker måste du använda parallellt alternativ .



  1. Solr och MySQL, Hur håller man ett uppdaterat index, och behövs ens en DB om det är enkelt?

  2. MySQL främmande nyckel vid radering

  3. MySql-fel:Kan inte uppdatera tabellen i lagrad funktion/trigger

  4. Vad motsvarar varchar(max) i Oracle?