2 Stimmen

Schnellster Weg, um wiederholt eine große Tabelle abzufragen

Ich habe eine Tabelle mit 50 Millionen Datensätzen, aber einer kompakten Struktur (id, int1, int1, int2, int3). Alle relevanten Indizes sind implementiert.

Ich muss sie etwa 50 Mal für jede Nutzerinteraktion abfragen. Das dauert etwa 5 Sekunden, wenn ich normale vorbereitete Abfragen gegen den Datenbankserver verwende. Alle Abfragen sind einfache SELECT-Anweisungen.

Meine Frage ist: Was kann ich tun, um dies zu beschleunigen, selbst wenn dabei deutlich mehr Speicher verwendet wird? Die Locate-Methode für Abfragen ist nicht flexibel genug und das direkte Verwenden von Filtern in der Abfrage ist langsam.

Die Hauptabfrage, die ich ausführe, ist

select knowledge_id, knowledge_family_id, tag_level, tag_order, 
  total_title_direct_words, total_title_parenthesis_words from knowledge_tags 
  where dictionary_word_id = XX order by tag_level, tag_order

Kann mir jemand eine Strategie vorschlagen? Würde TVirtualTable die Geschwindigkeit erhöhen?

3voto

AlexSC Punkte 1691

Angesichts der Tatsache, dass es kein Problem ist, die gesamte Tabelle in den Speicher zu laden, schlage ich vor:

  1. Führen Sie eine Abfrage aus, um alle Datensätze auszuwählen
  2. Gehen Sie einmal durch den Datensatz, um die Datensätze in eine Instanz von TObjectList zu kopieren, wobei TMyRecord eine Klasse ist, die alle Felder eines Datensatzes enthalten kann; so haben Sie jetzt eine Kopie des Datensatzes in einer Objektliste
  3. Sortieren Sie die Liste (oder wählen Sie sie korrekt sortiert aus), wenn möglich, damit Sie bei Bedarf eine binäre Suche durchführen können
  4. Geben Sie den Datensatz frei und arbeiten Sie nur mit der Liste.

In diesem Szenario umgehen Sie alle Datensatzüberköpfe und jede Suche wird viel schneller sein.

Ein Beispiel für TMyRecord ist:

interface

type
  TMyRecord = class
  private
    FId: Integer;
    FCol1: Integer;
    FCol2: Integer;
    FCol3: Integer;
    FCol4: Integer;
  public
    constructor Create(aId, aCol1, aCol2, aCol3, aCol4: Integer);
    property Id: Integer read FId write FId;
    property Col1: Integer read FCol1 write FCol1;
    property Col2: Integer read FCol2 write FCol2;
    property Col3: Integer read FCol3 write FCol3;
    property Col4: Integer read FCol4 write FCol4;
  end;

implementation

constructor TMyRecord.Create(aId, aCol1, aCol2, aCol3, aCol4: Integer);
begin
  FId := aId;
  FCol1 := aCol1;
  FCol2 := aCol2;
  FCol3 := aCol3;
  FCol4 := aCol4;
end;

2voto

EProgrammerNotFound Punkte 2393

Meiner Meinung nach wäre es viel schneller, alle Daten in einem TClientDataSet zu laden und FINDKEY zu verwenden, um diese Datensätze zu suchen.

Um FindKey() zu verwenden, müssen Sie Indizes wie folgt definieren:

Cds.IndexDefs.ADD('IDX1', 'FieldA;FieldB',[]);
Cds.IndexName := 'IDX1';
if Cds.FindKey([A,B]) then begin
  //Etwas machen
end;

Sie können auch mehrere Indizes erstellen und sie bei Bedarf nutzen:

Cds.IndexDefs.ADD('IDX1', 'FieldA;FieldB',[]);
Cds.IndexDefs.ADD('IDX2', 'FieldD;FieldB',[]);
Cds.IndexDefs.ADD('IDX3', 'FieldA;FieldC',[]);  

if SeekAB then 
  Cds.IndexName := 'IDX1'
else if SeekDB then 
  Cds.IndexName := 'IDX2'
else 
  Cds.IndexName := 'IDX3';

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X