Frage

Ich habe ein paar großen Tische (188m und 144m Zeilen) Ich brauche von Ansichten zu füllen, aber jede Ansicht enthält ein paar hundert Millionen Zeilen (Strang ziehen pseudo-dimensional modellierten Daten in eine flache Form). Die Tasten auf jeder Tabelle sind über 50 Verbund Bytes der Spalten. Wenn die Daten in Tabellen waren, konnte ich immer denke über sp_rename mit der anderen neuen Tabelle zu machen, aber das ist nicht wirklich eine Option.

Wenn ich eine einzelne INSERT-Operation zu tun, verwendet der Prozess eine riesige Menge von Transaktionsprotokollraum, typicalyl Einreichung es auf und veranlasst eine Menge Ärger mit dem DBAs. (Und ja, ist dies wahrscheinlich ein Job der DBAs behandeln sollen / Design / Architekt)

Ich kann SSIS verwenden und die Daten in die Zieltabelle mit Batch-Commits streamen (aber die Daten über das Netzwerk übertragen werden benötigt, da wir SSIS-Pakete auf dem Server nicht ausgeführt werden dürfen).

Jede andere Dinge als den Prozess zu unterteilen in mehrere INSERT-Operationen eine Art Schlüssel die Zeilen in verschiedenen Chargen zu verteilen und eine Schleife zu tun?

War es hilfreich?

Lösung

Sie können Ihre Daten partitionieren und Ihre Daten in einem Cursor-Schleife einzufügen. Das wäre fast die gleiche wie SSIS batchinserting sein. Aber läuft auf dem Server.

create cursor ....
select YEAR(DateCol), MONTH(DateCol) from whatever

while ....
    insert into yourtable(...)
    select * from whatever 
    where YEAR(DateCol) = year and MONTH(DateCol) = month
end

Andere Tipps

Hat die Ansicht, jede Art von eindeutigen Identifikator / Kandidatenschlüssel? Wenn ja, Sie wählen könnten, um diese Zeilen in eine Arbeitstabelle mit:

SELECT key_columns INTO dbo.temp FROM dbo.HugeView;

(Wenn es sinnvoll ist, setzen Sie vielleicht diese Tabelle in eine andere Datenbank, vielleicht mit Modell SIMPLE Recovery, die Log-Aktivität stört Ihre primäre Datenbank zu verhindern. Dies sollte viel weniger erzeugen ohnehin einzuloggen, und Sie können bis frei, die Platz in der anderen Datenbank, bevor Sie wieder aufnehmen, falls das Problem ist, dass Sie sich rundum unzureichenden Speicherplatz verfügen.)

Dann können Sie etwas tun, 10.000 Zeilen zu einer Zeit eingeführt wird, und das Protokoll zwischen Sicherung:

SET NOCOUNT ON;

DECLARE
    @batchsize INT,
    @ctr INT,
    @rc INT;

SELECT
    @batchsize = 10000,
    @ctr = 0;

WHILE 1 = 1
BEGIN
    WITH x AS
    (
        SELECT key_column, rn = ROW_NUMBER() OVER (ORDER BY key_column)
        FROM dbo.temp
    )
    INSERT dbo.PrimaryTable(a, b, c, etc.)
        SELECT v.a, v.b, v.c, etc.
        FROM x
        INNER JOIN dbo.HugeView AS v
        ON v.key_column = x.key_column
        WHERE x.rn > @batchsize * @ctr
        AND x.rn <= @batchsize * (@ctr + 1);

    IF @@ROWCOUNT = 0
        BREAK;

    BACKUP LOG PrimaryDB TO DISK = 'C:\db.bak' WITH INIT;

    SET @ctr = @ctr + 1;
END

Das ist alles aus der Spitze von meinem Kopf, so schneidet nicht / Paste / laufen, aber ich denke, die allgemeine Idee ist.

Beachten Sie, dass, wenn Sie regelmäßig Datenbank nehmen und Log-Sicherungen Sie wahrscheinlich eine vollständige starten Sie Ihre Log-Kette immer wieder nehmen wollen.

Ich weiß, das ist ein alter Thread, aber ich habe eine generische Version von Arthur Cursor Lösung:

--Split a batch up into chunks using a cursor.
--This method can be used for most any large table with some modifications
--It could also be refined further with an @Day variable (for example)

DECLARE @Year INT
DECLARE @Month INT

DECLARE BatchingCursor CURSOR FOR
SELECT DISTINCT YEAR(<SomeDateField>),MONTH(<SomeDateField>)
FROM <Sometable>;


OPEN BatchingCursor;
FETCH NEXT FROM BatchingCursor INTO @Year, @Month;
WHILE @@FETCH_STATUS = 0
BEGIN

--All logic goes in here
--Any select statements from <Sometable> need to be suffixed with:
--WHERE Year(<SomeDateField>)=@Year AND Month(<SomeDateField>)=@Month   


  FETCH NEXT FROM BatchingCursor INTO @Year, @Month;
END;
CLOSE BatchingCursor;
DEALLOCATE BatchingCursor;
GO

Dieses löste das Problem auf Lasten unserer großen Tabellen.

Es gibt keine Feenstaub, das wissen Sie.

Ohne Einzelheiten über die tatsächliche Schema zu wissen, übertragen wird, eine generische Lösung wäre genau so, wie Sie es beschreiben: divide Verarbeitung in mehrere Einsätze und verfolgen die Taste (n). Dies ist eine Art von Pseudo-Code T-SQL:

create table currentKeys (table sysname not null primary key, key sql_variant not null);
go

declare @keysInserted table (key sql_variant);
declare @key sql_variant;
begin transaction
do while (1=1)
begin
    select @key = key from currentKeys where table = '<target>';
    insert into <target> (...)
    output inserted.key into @keysInserted (key)
    select top (<batchsize>) ... from <source>
    where key > @key
    order by key;

    if (0 = @@rowcount)
       break; 

    update currentKeys 
    set key = (select max(key) from @keysInserted)
    where table = '<target>';
    commit;
    delete from @keysInserted;
    set @key = null;
    begin transaction;
end
commit

Es würde noch komplizierter, wenn Sie für die parallelen Reihen zulassen mögen und die Schlüssel partitionieren.

Sie könnten den BCP-Befehl verwenden, um die Daten zu laden und die Stapelgröße Parameter

http://msdn.microsoft.com/en-us/library /ms162802.aspx

Zweistufenverfahren

  • BCP OUT-Daten von Ansichten in Textdateien
  • BCP IN Daten aus Textdateien in den Tabellen mit Losgröße Parametern

Das sieht wie ein Job für good ol‘ BCP .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top