sql >> Database >  >> RDS >> Oracle

Optimale manier om gespecificeerde rijen te VERWIJDEREN uit Oracle

Voordat mijn vragen worden beantwoord, zou ik het als volgt aanpakken:

Minimaliseer het aantal verklaringen en het werk dat ze doen in relatieve termen.

Alle scenario's gaan ervan uit dat je een tabel met ID's hebt (PURGE_IDS ) om te verwijderen uit TABLE_1 , TABLE_2 , enz.

Overweeg het gebruik van CREATE TABLE AS SELECT voor echt grote verwijderingen

Als er geen gelijktijdige activiteit is en u 30+% van de rijen in een of meer van de tabellen verwijdert, verwijder dan niet; voer een create table as select met de rijen die u wilt behouden, en verwissel de nieuwe tafel voor de oude tafel. INSERT /*+ APPEND */ ... NOLOGGING is verrassend goedkoop als je het kunt betalen. Zelfs als je wel wat gelijktijdige activiteit hebt, kun je mogelijk online tafelherdefinitie gebruiken om de tafel ter plekke opnieuw op te bouwen.

Voer geen DELETE-instructies uit waarvan u weet dat deze geen rijen zullen verwijderen

Als er een ID-waarde bestaat in maximaal een van de zes tabellen, houd dan bij welke ID's u hebt verwijderd - en probeer die ID's niet uit een van de andere tabellen te verwijderen.

CREATE TABLE TABLE1_PURGE NOLOGGING
AS 
SELECT ID FROM PURGE_IDS INNER JOIN TABLE_1 ON PURGE_IDS.ID = TABLE_1.ID;

DELETE FROM TABLE1 WHERE ID IN (SELECT ID FROM TABLE1_PURGE);

DELETE FROM PURGE_IDS WHERE ID IN (SELECT ID FROM TABLE1_PURGE);

DROP TABLE TABLE1_PURGE;

en herhaal.

Concurrency beheren als dat moet

Een andere manier is om PL/SQL-looping over de tabellen te gebruiken, waarbij een rowcount-limited delete-statement wordt uitgegeven. Dit is hoogstwaarschijnlijk geschikt als er een aanzienlijke gelijktijdige belasting van invoegen/bijwerken/verwijderen is voor de tabellen waartegen u de verwijderingen uitvoert.

declare
  l_sql varchar2(4000);
begin
  for i in (select table_name from all_tables 
             where table_name in ('TABLE_1', 'TABLE_2', ...)
             order by table_name);
  loop
    l_sql := 'delete from ' || i.table_name || 
             ' where id in (select id from purge_ids) ' || 
             '   and rownum <= 1000000';
    loop
      commit;
      execute immediate l_sql;
      exit when sql%rowcount <> 1000000;  -- if we delete less than 1,000,000
    end loop;                             -- no more rows need to be deleted!
  end loop;
  commit;
end;


  1. ScaleGrid op shortlist voor 2017-2018 Cloud Awards-programma

  2. Tellen op basis van voorwaarde in SQL Server

  3. Wat is de opgeslagen procedure en waarom de opgeslagen procedure?

  4. Een lijst met partitieschema's retourneren in SQL Server (T-SQL)