sql >> Databasteknik >  >> RDS >> Oracle

Optimalt sätt att RADERA specificerade rader från Oracle

Innan mina frågor besvaras så här skulle jag gå tillväga:

Minimera antalet utlåtanden och det arbete de utför i relativa termer.

Alla scenarier förutsätter att du har en tabell med ID:n (PURGE_IDS ) för att radera från TABLE_1 , TABLE_2 , etc.

Överväg att använda CREATE TABLE AS SELECT för riktigt stora raderingar

Om det inte finns någon samtidig aktivitet och du tar bort 30+ % av raderna i en eller flera av tabellerna, ta inte bort; utför en create table as select med de rader du vill behålla och byt ut det nya bordet mot det gamla. INSERT /*+ APPEND */ ... NOLOGGING är förvånansvärt billigt om du har råd. Även om du har viss samtidig aktivitet, kanske du kan använda Online Table Redefinition för att bygga om tabellen på plats.

Kör inte DELETE-satser som du vet inte kommer att radera några rader

Om ett ID-värde finns i högst en av de sex tabellerna, håll sedan reda på vilka ID:n du har tagit bort - och försök inte ta bort dessa ID:n från någon av de andra tabellerna.

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;

och upprepa.

Hantera samtidighet om du måste

Ett annat sätt är att använda PL/SQL-looping över tabellerna och utfärda en radbegränsad delete-sats. Detta är med största sannolikhet lämpligt om det finns en betydande insättning/uppdatering/borttagning av samtidig belastning mot tabellerna du kör borttagningarna mot.

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. Kör sp_msforeachdb i en Java-applikation

  2. Hur man kör Raw SQL i SQLAlchemy

  3. 2 sätt att återvända Julian Day i SQLite

  4. Hur utför man en SQLite-fråga i en Android-applikation?