Frage

In meiner Anwendung verwende ich Tadoquery mit Select (MSSQL) und bin damit verknüpft. Ich muss ungefähr Millionen Datensätze und Bewerben einfügen.

Also, was ich im SQL Server -Profiler sehe? Ich sehe das für jeder Eingefügte Zeile Wir haben 3 Abfragen: sp_prepare des Einfügenskripts, sp_execute es mit einigen Werten und sp_unprepare.

Ich möchte nur SQL vorbereiten einmal Für alle Datensätze vor dem Einfügen und nicht aufpassen. Wie kann ich es tun?

Hinzugefügt:

In der Abfrage habe ich ein Skript für die gespeicherte Verfahrensausführung:

tmpQuery := DefineQuery(FConnection, [
  'exec up_getOperatorDataSet ',
  '  @tablename     = :tablename, ',
  '  @operator      = :operator, ',
  '  @forappend     = :forappend, ',
  '  @withlinksonly = :withlinksonly, ',
  '  @ids           = :ids '
], [
  Param(ftString, sTableName),
  Param(ftInteger, FOperatorId),
  Param(ftBoolean, opForAppendOnly in OpenParams),
  Param(ftBoolean, opOnlyWithModelLinks in OpenParams),
  Param(ftString, sIds)
], Result);

Es wählt alle Felder aus der Tabelle aus Stablename mit einigen Parametern.

Beispiel für das Einfügen von Profiler:

Schritt 1:

declare @p1 int
set @p1=486
exec sp_prepare @p1 output,N'@P1 int,@P2 int,@P3 datetime,@P4 int,@P5 int,@P6 int,@P7 int,@P8 int,@P9 varchar(128),@P10 bit,@P11 numeric(19,4),@P12 smallint,@P13 smallint,@P14 smallint,@P15 smallint',N'insert into parser_prices
  (operator_id, request_id, date, nights, model_hotel_id, model_meal_id, model_room_id, model_htplace_id, spo, hotelstop, price, frout_econom, frout_business, frback_econom, frback_business)
values
  (@P1, @P2, @P3, @P4, @P5, @P6, @P7, @P8, @P9, @P10, @P11, @P12, @P13, @P14, @P15)
',1
select @p1

Schritt 2:

exec sp_execute 486,21,2000450,'2009-12-04 00:00:00',14,2118,22,-9555,18,'2009-10.MSK.Bali.13.10.09-27.03.10',0,15530.0000,3,3,3,3

Schritt 3:

exec sp_unprepare 486

und es ist für alle der neuen Reihen.

War es hilfreich?

Lösung 4

Die Antwort war der Anbieter, der in Tadoconnection verwendet wurde. Von msdasql auf SQLOLEDB umgestellt und ist gerade jetzt ohne zusätzliche Abfragen.

Andere Tipps

Da Sie eine gespeicherte Prozedur anrufen und nicht eine Inline -Abfrage in Ihrem Code, behandelt SQL Server jeden Anruf mit dem gespeicherten Proc als separaten Anruf, und es wird dies jedes Mal vorbereitet und sich nicht vorbereiten. Ich bin mir nicht sicher, ob es einen Weg gibt.

Wenn alles, was in dem gespeicherten Proc geschieht, aus einer Abfrage in Ihrem Code erfolgen kann, können Sie eine solche Struktur verwenden, die die SQL -Anweisung nur zum ersten Mal vorbereitet:

{Prepare the insert query}
ADOQuery1.SQL.Append('INSERT INTO Tablename');
ADOQuery1.SQL.Append('(StringField1, IntField2)');             {repeat as necessary}
ADOQuery1.SQL.Append('VALUES (:sFieldValue1, :sFieldValue2)'); {repeat as necessary}
ADOQuery1.SQL.Prepare;

{In a For, While, Repeat loop, use:}
ADOQuery1.ParamByName('sFieldValue1').AsString := 'Value for field 1';
ADOQuery1.ParamByName('sFieldValue2').AsInteger := 2;
ADOQuery1.ExecSQL;

Entschuldigung, wenn ich die Eigenschafts- und Methodennamen für die Adoquery -Komponente nicht ganz auf meinem Delphi -PC habe und die Tado -Komponenten normalerweise nicht anhand Tdataset -Konzept.

Gedanken...

  1. Sie müssen keinen gespeicherten Verfahrensanruf vorbereiten. Tatsächlich ist es bereits vorbereitet. Sie können es in den meisten Client -Implementierungen abschieben.

  2. Möglicherweise können Sie es für eine Million Zeilen auf einmal nicht tun. Du hast ein Batchgrößengrenze (z. B. ein einzelner DB -Aufruf) von 256 MB (Angenommen unter standardmäßiger 4K -Netzwerkpakete).

  3. In anderen Client -Implementierungen können Sie eine festlegen "Chargengröße"(anderes Konzept zu Punkt 2), sagen wir 10.000, so dass Sie nur 100 Anrufe tätigen, nicht eine Million.

Ich denke, dass die anderen Antworten möglicherweise gut dazu beitragen, die Leistung zu stimmen, obwohl ich denke, mit welcher Methode Sie auf den TClientDataset zugreifen können, spielt keine Rolle, da das tatsächliche Datenbankaktualisierung in jedem Fall separat (und automatisch generiert) ist.

Wenn das Update als separate Vorbereitung für jede Zeile funktioniert, scheint es eine schlechte Designauswahl von Borland zu sein, da es offensichtlich ist, dass die Aktualisierung vieler Zeilen dieselbe Abfrage erfordert, nur mit unterschiedlichen Parametern.

Andererseits war TclientDataset für In-Memory-Datenbanken gedacht, was relativ kleine Datenbanken bedeutet. Die Verwendung einer Million Zeilen geht wahrscheinlich über den beabsichtigten Anwendungsfall hinaus.

Andererseits kann es möglicherweise problematisch sein, den ClientDataset von Ihrer Anwendung aus Ihrer Bewerbung auszutauschen. Ich würde sagen, dass ich für den leistungssensiblen Teil Ihrer Anwendung die geänderten Zeilen selbst verfolgen und eine manuelle Update -Routine mit den oben genannten Routinen schreiben würde. Außerdem können Sie versuchen, den Quellcode des TclientDataset zu ändern, um ihn effizienter zu gestalten oder die Methode zu überschreiben, die die Änderungen anwendet.

(Persönlich verwende ich SQLite3 für die Speicherung in meinen Programmen, sodass ClientDataset wenig nützlich ist und ich nicht viel damit gespielt habe).

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