Amélioration performance bases Paradox

ludo2223 Messages postés 49 Date d'inscription jeudi 4 septembre 2008 Statut Membre Dernière intervention 31 janvier 2010 - 4 sept. 2009 à 17:52
ludo2223 Messages postés 49 Date d'inscription jeudi 4 septembre 2008 Statut Membre Dernière intervention 31 janvier 2010 - 15 sept. 2009 à 12:25
Bonjour à tous,

Je travaille actuellement sur un logiciel multimédia et j'ai besoin de parcourir l'ensemble d'un répertoire (sous répertoires et fichiers) pour stocker la liste dans une base de type Paradox.

J'ai donc mis au point un algo récursif qui parcours l'arborescence (parcours 250 éléments en 100ms) et extrait la date, heure de modification et la taille des fichiers.

Pour stocker tout ça j'utilise un objet TTable ouvert en mettant le chemin de la table dans tableName et Active:= True.

Voici mon code d'ajout des données :

TABLE_info.indexFieldNames:='Key';
TABLE_info.append;
TABLE_info.fields[0].value:=newKey;
TABLE_info.fields[1].value:=parcours;
TABLE_info.fields[2].value:=ENREGISTREMENT_DE_TYPE_REPERTOIRE;
TABLE_info.fields[3].value:=0; // taille du repertoire
TABLE_info.fields[4].value:=dateDerniereMAJ;
TABLE_info.fields[5].value:=heureDerniereMAJ;
TABLE_info.post;

A la fin je fait un active := False et un Free.

Mon problème c'est que quand je met ces 9 lignes le temps passe de 100ms à 169 000 ms !!!

Mon algo est récursif dans le sens ou la fonction se rappelle lorsqu'elle tombe sur un répertoire afin d'en traiter le sous arbre. J'ai testé la fonction et elle parcours bien l'ensemble de l'arbre (à l'aide de findfirst) et ce une seule fois.

J'ai donc pensé que l'ouverture en parallèle des tables causé par la récursivité pausait problème. J'ai donc essayé d'ouvrir et de fermer à chaque itération (approx 169 000 ms aussi).

J'ai également testé ADO mais je ne suis pas parvenu à la faire fonctionné correctement.

Je fait donc appel à vous, pour me donner des pistes sur des méthodes d'insertion en base de données paradox plus performantes.

Si vous constatez quelque chose d'étrange dans mon raisonnement n'hésitez pas à me demander.

Merci d'avance pour votre réponses.

Ludovic

24 réponses

cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
5 sept. 2009 à 17:53
Bonjour,
il faudrait connaître exactement quel est le code qui prend du temps..
il faut faire des pointages plus précis.

cantador
0
ludo2223 Messages postés 49 Date d'inscription jeudi 4 septembre 2008 Statut Membre Dernière intervention 31 janvier 2010
5 sept. 2009 à 18:44
Bonjour,

Merci pour votre réponse.

Les lignes de code qui prennent du temps sont les 9 que j'ai mises dans mon post.

Si elle sont présentes il faut 169 000 ms et si elles sont commentées il faut 100 ms.

Voulez-vous dire, laquelle parmi les 9 ?

Cordialement

Ludovic
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
5 sept. 2009 à 22:11
oui bien sûr

cantador
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
6 sept. 2009 à 12:17
Salut,

Tu dois pouvoir faire des lots j'imagine. Connais pas TTable, mais peut être qu'en faisant X append avant de faire un post, ça irait mieux.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
ludo2223 Messages postés 49 Date d'inscription jeudi 4 septembre 2008 Statut Membre Dernière intervention 31 janvier 2010
7 sept. 2009 à 10:33
Bonjour,

Merci pour vos réponses.

J'ai fait d'autres tests.

- avec insert (fait le post automatiquement) : plus rapide (118 000 ms)
- avec append puis post : (169 000 ms)
- AppendRecord(tableau) : (170 000 ms)
- InserRecord(tableau) : (170 000 ms)

Ce que je ne comprend pas c'est le fait qu'InsertRecord soit moins performant qu'un Insert fait à la main.

J'ai essayé de faire des append non suivi d'un post et de faire le post à la fin mais il me dit que la table n'est pas dans un état permettant post.

Je continue les tests.

Si vous avez d'autres idées pour ajouter des d'enregistrement dans une table paradox.
(mon algo est récursif)

Cordialement

Ludovic
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
7 sept. 2009 à 11:56
oui, mais tu n'as toujours pas répondu à la question :

TABLE_info.indexFieldNames:='Key';
TABLE_info.append;
TABLE_info.fields[0].value:=newKey;
TABLE_info.fields[1].value:=parcours;
TABLE_info.fields[2].value:=ENREGISTREMENT_DE_TYPE_REPERTOIRE;
TABLE_info.fields[3].value:=0; // taille du repertoire
TABLE_info.fields[4].value:=dateDerniereMAJ;
TABLE_info.fields[5].value:=heureDerniereMAJ;
TABLE_info.post;

quelle est la ligne qui prend du temps ?

cantador
0
ludo2223 Messages postés 49 Date d'inscription jeudi 4 septembre 2008 Statut Membre Dernière intervention 31 janvier 2010
7 sept. 2009 à 14:08
Je ne suis pas parvenu à le calculer, avec GetTickCount il me renvoie 0 si je calcule le temps entre chaque ligne.

Avez-vous une autre méthode de calcul du temps ?

En faisant insert à la place de append et post je gagne pas mal de temps.

Je pense donc que c'est la méthode d'ajout (insert ou append) qui prend le plus de temps. Je suis d'accord qu'il faudrait que je parvienne à le vérifier.

Merci d'avance pour votre réponse.

Ludovic
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
7 sept. 2009 à 14:29
Une classe de chronométrage, codée à l'arrache :

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;

type TPerformanceCounter = class
  public
    constructor Create;
    procedure Start;
    function Stop: Int64;
  private
    _nFrequency: Int64;
    _nBegin: Int64;
end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TPerformanceCounter.Create;
begin
  inherited;
  QueryPerformanceFrequency(_nFrequency);
end;

procedure TPerformanceCounter.Start;
begin
  QueryPerformanceCounter(_nBegin);
end;

function TPerformanceCounter.Stop: Int64;
var
  nEnd: Int64;
begin
  QueryPerformanceCounter(nEnd);
  Result:= ((nEnd - _nBegin) * 1000000) div _nFrequency;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  counter: TPerformanceCounter;
begin
  counter:= TPerformanceCounter.Create;

  counter.Start;
  Sleep(2);
  ShowMessage(IntToStr(counter.Stop) + ' microsecondes');
  counter.Start;
  Sleep(10);
  ShowMessage(IntToStr(counter.Stop) + ' microsecondes');

  FreeAndNil(counter);
end;

end.
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
7 sept. 2009 à 17:05
bien obligé de faire un post derrière
un append pour chaque enregistrement..

un append peut prendre du temps si par exemple la table est volumineuse..

118 000 ms, ce qui fait environ 2minutes..
ça fait beaucoup je trouve...

il doit y avoir un truc quelque part je pense...

combien y a t-il d'enregistrements au maximum ?

cantador
0
ludo2223 Messages postés 49 Date d'inscription jeudi 4 septembre 2008 Statut Membre Dernière intervention 31 janvier 2010
7 sept. 2009 à 17:20
Merci pour vos réponses.

Pour le temps je testerais avec la classe que vous m'avez donné.

Au début je pars avec une table vide et je la rempli avec 250 enregistrements environ.

Visiblement un insert est plus performant qu'un append / post (il ne met pas les enregistrement dans le même ordre, non ?)

Je viens de regarder dans l'administrateur bde et j'ai tenté d'améliorer les paramètres de ram, nombre d'handle... C'est très légèrement mieux.

Par contre dans Administrateur BDE -> Pilotes -> Natif -> Paradox j'ai version 4.0 !
Savez-vous comment mettre à jour vers la 7.0 ? (je n'ai pas trouvé sur google)

Je suis étonné qu'il n'utilise pas une version plus récente car je suis sous Delphi 2009 (Win Xp).

Merci d'avance pour vos réponses.
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
7 sept. 2009 à 17:23
Un post par append ?
Bah il doit y avoir un autre moyen de faire des lots alors.

Peut être avec TBatchMove ?
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
7 sept. 2009 à 18:58
avec 250 enregistrements environ.

c'est tout petit petit.
il y a donc bien un truc.
la version 7 va améliorer c'est sûr
(il faut la choisir au moment de créer la table)
mais pas diviser les temps par 2..

pour aviter append et post, il faut utiliser :
appendrecord();

mais je suis persuadé que la boucle de recherche des fichiers doit prendre du temps...

cantador
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
8 sept. 2009 à 08:06
et je ferai d'abord la recherche en plaçant les données dans un tableau dynamique puis je stockerai à la fin tout le tableau dans la table.

je boucle sur le tableau de 0 à n - 1 et je stocke :
var
tabR : array of string;
i:integer;
begin
setlength(tabR,Maxnbffich);
for i:= 0 to high(tabR) do
begin
MaTable.Append;
Matable.Chp1.Value := tabR[i];
--
--
MaTable.Post;
end;
end;


cantador
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
8 sept. 2009 à 08:09
setlength(tabR,Maxnbffich);

>> opérations de recherche de fichiers<<<


for i:= 0 to high(tabR) do




cantador
0
ludo2223 Messages postés 49 Date d'inscription jeudi 4 septembre 2008 Statut Membre Dernière intervention 31 janvier 2010
8 sept. 2009 à 09:30
Bonjour,

Merci pour vos réponses.

J'avais essayé le tableau dynamique mais j'ai bloqué sur une chose. Ma fonction étant récursive elle doit renvoyer le tableau des résultats pour le sous-arbre. Ce paramètre doit être optionnel pour ne pas changer tout les appels dans l'application.

Je ne suis pas parvenu à passer en paramètre un tableau dynamique (5*x) optionnel. Le compilateur me demandait une valeur par défaut et lorsque j'en donnais une il me disait qu'il n'en fallait pas (ou mauvais type ?).

Il reste aussi le problème de la concaténation de tableaux multi-colonnes.

Si vous avez des pistes pour les deux problèmes ;)

Merci d'avance et bonne matinée

Ludovic
0
ludo2223 Messages postés 49 Date d'inscription jeudi 4 septembre 2008 Statut Membre Dernière intervention 31 janvier 2010
8 sept. 2009 à 09:31
re

J'oubliais, je n'ai pas trouvé la mise à jour vers Paradox 7.

Vous avez une idée ?

Merci ;)
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
8 sept. 2009 à 10:24
Je ne suis pas parvenu à passer en paramètre un tableau dynamique (5*x) optionnel. Le compilateur me demandait une valeur par défaut et lorsque j'en donnais une il me disait qu'il n'en fallait pas (ou mauvais type ?).

Bah tu as un paquet de façon de t'en sortir, par exemple avec une surcharge :
procedure DisplayArray(lpArray: Array of String); overload;
var
  nI: Integer;
  lpStr: String;
begin
  lpStr:= '';
  for nI:= 0 to High(lpArray) do
    lpStr:= lpStr + lpArray[nI];
  ShowMessage(lpStr);
end;

procedure DisplayArray(); overload;
begin
  DisplayArray([]);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  lpArray: Array of String;
begin
  SetLength(lpArray, 2);
  lpArray[0]:= 'toto';
  lpArray[1]:= 'titi';
  DisplayArray(lpArray);
  DisplayArray();
  lpArray:= nil;
end;


Il reste aussi le problème de la concaténation de tableaux multi-colonnes.

Est ce vraiment un problème ?
procedure TForm1.Button1Click(Sender: TObject);
var
  lpArray1: Array of Array of String;
  lpArray2: Array of Array of String;
  nArray1Len: Integer;
  lpResult: String;
  nI: Integer;
begin
  SetLength(lpArray1, 2);
  SetLength(lpArray1[0], 2);
  SetLength(lpArray1[1], 2);
  lpArray1[0, 0]:= '1';
  lpArray1[0, 1]:= 'a';
  lpArray1[1, 0]:= '2';
  lpArray1[1, 1]:= 'b';

  SetLength(lpArray2, 2);
  SetLength(lpArray2[0], 2);
  SetLength(lpArray2[1], 2);
  lpArray2[0, 0]:= '3';
  lpArray2[0, 1]:= 'c';
  lpArray2[1, 0]:= '4';
  lpArray2[1, 1]:= 'd';

  // Concaténation
  nArray1Len:= Length(lpArray1);
  SetLength(lpArray1, nArray1Len + Length(lpArray2));
  for nI:= 0 to High(lpArray2) do
  begin
    SetLength(lpArray1[nArray1Len + nI], 2);
    lpArray1[nArray1Len + nI][0]:= lpArray2[nI][0];
    lpArray1[nArray1Len + nI][1]:= lpArray2[nI][1];
  end;

  // Affichage
  for nI:= 0 to High(lpArray1) do
  begin
    lpResult:= lpResult + lpArray1[nI][0];
    lpResult:lpResult + ' ';
    lpResult:= lpResult + lpArray1[nI][1];
    lpResult:= lpResult + sLineBreak;
  end;
  ShowMessage(lpResult);

  // Libération
  for nI:= 0 to High(lpArray1) do
  begin
    lpArray1[nI]:= nil;
  end;
  lpArray1:= nil;

  for nI:= 0 to High(lpArray2) do
  begin
    lpArray2[nI]:= nil;
  end;
  lpArray2:= nil;
end;
0
ludo2223 Messages postés 49 Date d'inscription jeudi 4 septembre 2008 Statut Membre Dernière intervention 31 janvier 2010
8 sept. 2009 à 11:44
Merci beaucoup pour ta réponse.

Je teste tout ca.

Bon app ;)
0
ludo2223 Messages postés 49 Date d'inscription jeudi 4 septembre 2008 Statut Membre Dernière intervention 31 janvier 2010
8 sept. 2009 à 17:24
J'ai essayé de mettre sous forme de fonction :

procedure concat(source,dest:Array of String);
var
nArray1Len,nI,nJ:integer;

begin
nArray1Len:= Length(source);

SetLength(source, nArray1Len + Length(dest));

for nI:= Low(dest) to High(dest) do
begin

SetLength(source[nArray1Len + nI], Length(source[Low(source)]));

for nJ:= Low(source[nI]) to High(source[nI]) do
begin
source[nArray1Len + nI][nJ]:= dest[nI][nJ];
end;
end;
end;

Le setLength ne compile pas en disant : Types incompatibles.
Si je remplace source par un Array of String créé dans Var ca compile mais il bloque sur Low / High en disant que ces fonctions ne peuvent être appelés sur une chaine longue.

Quelle est la différence entre un tableau en paramètre et un tableau créé dans Var ?

Que dois-je faire ?

Merci d'avance pour vos réponses.

Ludovic
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
8 sept. 2009 à 17:41
Houlà. Pas compris ton code moi.

source,dest:Array of String

C'est des tableaux à une dimension, alors que les miens sont à deux dimension vu que tu avais dit "tableaux multi-colonnes".
0
Rejoignez-nous