Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Czy istnieje sposób na ulepszenie zapytania MERGE?

Gdybyś miał ogromny problemy z Twoim podejściem, najprawdopodobniej brakuje Ci indeksu w kolumnie clean.id , który jest wymagany dla Twojego podejścia, gdy MERGE używa dual jako źródło dla każdego wiersza.

Jest to mniej prawdopodobne, gdy mówisz id to klucz podstawowy .

Więc w zasadzie dobrze myślisz, a zobaczysz plan realizacji podobny do poniższego:

---------------------------------------------------------------------------------------------------
| 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)

Tak więc plan wykonania jest w porządku i działa skutecznie, ale ma jeden problem.

Pamiętaj, zawsze używasz indeksu, będziesz zadowolony podczas przetwarzania kilku wierszy, ale nie będzie on skalowany .

Jeśli przetwarzasz miliony rekordów, możesz wrócić do przetwarzania dwuetapowego,

  • wstaw wszystkie wiersze do tabeli tymczasowej

  • wykonać pojedynczy MERGE oświadczenie za pomocą tabeli tymczasowej

duża zaleta jest to, że Oracle może otworzyć hash join i pozbądź się dostępu do indeksu dla każdego z milionu wiersze.

Oto przykład testu clean tabela zainicjowana za pomocą 1M id (nie pokazano) i wykonywanie wstawek 1M i aktualizacji 1M:

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)

Test trwa około. 10 sekund, czyli mniej niż połowa Twojego podejścia z MERGE używając dual .

Jeśli to nadal nie wystarczy, będziesz musiał użyć opcji równoległej .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. jak wysłać e-mail przez Pl/sql

  2. Alternatywa dla POWROTU z INSERT...SELECT

  3. Pobieranie wartości z tabeli Oracle DB do pola listy w c# /wpf

  4. Oracle 11g SQL — zastąpienie NULL zerem, gdy zapytanie ma PIVOT

  5. Importowanie danych z pliku csv