IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Interfaces de programmation Oracle Discussion :

[OCILIB] Problème de compilation


Sujet :

Interfaces de programmation Oracle

  1. #1
    Nouveau Candidat au Club
    Inscrit en
    Février 2003
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 18
    Points : 1
    Points
    1
    Par défaut [OCILIB] Problème de compilation
    Bonjour,
    j'essaye de compiler sans succès OCILIB
    Je travaille sur une Fedora Core 4 (mais j'ai exactement le même soucis sous une Centos 4) .
    Le configure passe mais quand je lance le make c'est le drame :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
     
    [oracle@fr-31-01-06-820 ocilib-3.4.0]$ make
    make  all-recursive
    make[1]: Entering directory `/home/oracle/ocilib-3.4.0'
    Making all in doc/html
    make[2]: Entering directory `/home/oracle/ocilib-3.4.0/doc/html'
    make[2]: Rien Ã* faire pour « all ».
    make[2]: Leaving directory `/home/oracle/ocilib-3.4.0/doc/html'
    Making all in src
    make[2]: Entering directory `/home/oracle/ocilib-3.4.0/src'
    /bin/sh ../libtool --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -I/opt/oracle/920/rdbms/public -I../include   -DOCI_IMPORT_LINKAGE -DOCI_CHARSET_ANSI   -g -O2 -MT libocilib_la-bind.lo -MD -MP -MF .deps/libocilib_la-bind.Tpo -c -o libocilib_la-bind.lo `test -f 'bind.c' || echo './'`bind.c
    mkdir .libs
     gcc -DHAVE_CONFIG_H -I. -I.. -I/opt/oracle/920/rdbms/public -I../include -DOCI_IMPORT_LINKAGE -DOCI_CHARSET_ANSI -g -O2 -MT libocilib_la-bind.lo -MD -MP -MF .deps/libocilib_la-bind.Tpo -c bind.c  -fPIC -DPIC -o .libs/libocilib_la-bind.o
    In file included from ocilib_defs.h:39,
                     from ocilib_types.h:39,
                     from ocilib_internal.h:38,
                     from bind.c:35:
    oci_import.h:49:17: error: oci.h: No such file or directory
    oci_import.h:50:18: error: orid.h: No such file or directory
    oci_import.h:51:20: error: oci8dp.h: No such file or directory
    In file included from ocilib_internal.h:38,
                     from bind.c:35:
    ocilib_types.h:81: error: syntax error before 'ub4'
    ocilib_types.h:81: warning: no semicolon at end of struct or union
    ocilib_types.h:83: error: syntax error before '}' token
    ocilib_types.h:94: error: syntax error before 'ub1'
     
    (... ca continue pendant 3 pages..)
    Une piste? il me manque un prérequis?

    Merci d'avance

  2. #2
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Points : 5 307
    Points
    5 307
    Par défaut
    oci_import.h:49:17: error: oci.h: No such file or directory
    cela signifie que les fichiers d'entête OCI ne sont pas trouvé par le compilateur...

    Fais une recherche du répertoire ou se trouve oci.h...
    Vincent Rogier.

    Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

    Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

    OCILIB (C Driver for Oracle)

    Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle

  3. #3
    Nouveau Candidat au Club
    Inscrit en
    Février 2003
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 18
    Points : 1
    Points
    1
    Par défaut
    un petit find . -name 'oci.h' dans le $ORACLE_HOME me donne :
    ./rdbms/demo/oci.h

  4. #4
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Points : 5 307
    Points
    5 307
    Par défaut
    bon, c'est de l'oracle 9.2 qui selon les plateformes avait les headers dans rdbms/demo au lieu de /rdbms/public...

    refait un configure comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ./configure --with-oracle-headers-path=$ORACLE_HOME/rdbms/demo
    Vincent Rogier.

    Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

    Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

    OCILIB (C Driver for Oracle)

    Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle

  5. #5
    Nouveau Candidat au Club
    Inscrit en
    Février 2003
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 18
    Points : 1
    Points
    1
    Par défaut
    c'est fait.

    l'erreur change

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
    Making check in src
    make[1]: Entering directory `/home/oracle/ocilib-3.4.0/src'
    /bin/sh ../libtool --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -I/opt/oracle/920/rdbms/demo -I../include   -DOCI_IMPORT_LINKAGE -DOCI_CHARSET_ANSI   -g -O2 -MT libocilib_la-bind.lo -MD -MP -MF .deps/libocilib_la-bind.Tpo -c -o libocilib_la-bind.lo `test -f 'bind.c' || echo './'`bind.c
    mkdir .libs
     gcc -DHAVE_CONFIG_H -I. -I.. -I/opt/oracle/920/rdbms/demo -I../include -DOCI_IMPORT_LINKAGE -DOCI_CHARSET_ANSI -g -O2 -MT libocilib_la-bind.lo -MD -MP -MF .deps/libocilib_la-bind.Tpo -c bind.c  -fPIC -DPIC -o .libs/libocilib_la-bind.o
    In file included from oci_import.h:49,
                     from ocilib_defs.h:39,
                     from ocilib_types.h:39,
                     from ocilib_internal.h:38,
                     from bind.c:35:
    /opt/oracle/920/rdbms/demo/oci.h:2159:21: error: ociextp.h: No such file or directory
    In file included from /opt/oracle/920/rdbms/demo/oci.h:2164,
                     from oci_import.h:49,
                     from ocilib_defs.h:39,
                     from ocilib_types.h:39,
                     from ocilib_internal.h:38,
                     from bind.c:35:
    /opt/oracle/920/rdbms/demo/ociap.h:192:17: error: nzt.h: No such file or directory
    In file included from /opt/oracle/920/rdbms/demo/oci.h:2164,
                     from oci_import.h:49,
                     from ocilib_defs.h:39,
                     from ocilib_types.h:39,
                     from ocilib_internal.h:38,
                     from bind.c:35:
    /opt/oracle/920/rdbms/demo/ociap.h:6607: error: syntax error before 'nzttWallet'
    /opt/oracle/920/rdbms/demo/ociap.h:6611: error: syntax error before 'nzttWallet'
    /opt/oracle/920/rdbms/demo/ociap.h:6619: error: syntax error before 'nzttWallet'
    /opt/oracle/920/rdbms/demo/ociap.h:6630: error: syntax error before 'nzttPersona'
    /opt/oracle/920/rdbms/demo/ociap.h:6635: error: syntax error before 'nzttPersona'
    /opt/oracle/920/rdbms/demo/ociap.h:6639: error: syntax error before 'nzttPersona'
    /opt/oracle/920/rdbms/demo/ociap.h:6643: error: syntax error before 'nzttPersona'
    (...)
    /opt/oracle/920/rdbms/demo/ociap.h:6884: error: syntax error before 'nzttIdentity'
    In file included from /opt/oracle/920/rdbms/demo/oci.h:2179,
                     from oci_import.h:49,
                     from ocilib_defs.h:39,
                     from ocilib_types.h:39,
                     from ocilib_internal.h:38,
                     from bind.c:35:
    /opt/oracle/920/rdbms/demo/ocixad.h:73: error: syntax error before 'OCIExtProcContext'
    /opt/oracle/920/rdbms/demo/ocixad.h:78: error: syntax error before 'OCIExtProcContext'
    /opt/oracle/920/rdbms/demo/ocixad.h:83: error: syntax error before 'OCIExtProcContext'
    /opt/oracle/920/rdbms/demo/ocixad.h:89: error: syntax error before 'OCIExtProcContext'
    /opt/oracle/920/rdbms/demo/ocixad.h:92: error: syntax error before 'OCIExtProcContext'
    /opt/oracle/920/rdbms/demo/ocixad.h:95: error: syntax error before 'OCIExtProcContext'
    /opt/oracle/920/rdbms/demo/ocixad.h:98: error: syntax error before 'OCIExtProcContext'
    /opt/oracle/920/rdbms/demo/ocixad.h:102: error: syntax error before 'OCIExtProcContext'
    /opt/oracle/920/rdbms/demo/ocixad.h:143: error: syntax error before 'OCIExtProcContext'
    make[1]: *** [libocilib_la-bind.lo] Erreur 1
    make[1]: Leaving directory `/home/oracle/ocilib-3.4.0/src'
    make: *** [check-recursive] Erreur 1
    le fichiers manquants dont dans rdbms/public, je les copie dans démo

  6. #6
    Nouveau Candidat au Club
    Inscrit en
    Février 2003
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 18
    Points : 1
    Points
    1
    Par défaut
    bon, ca a compilé :-D

    reste plus qu'à tester...

    je dois faire des exports en fichier plats hyper performants (pour remplacer du cobol existant)

  7. #7
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Points : 5 307
    Points
    5 307
    Par défaut
    bon, ta config orcle aurait besoin des deux dossiers public et demo ??

    le plus simple serait d'ajouter les deux répertoires dans l'environnement car le configure de ocilib ne prend q'une seul répertoire...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    export CFLAGS="$CFLAGS -I$ORACLE_HOME/rdbms/public -I$ORACLE_HOME/rdbms/demo" 
    ./configure
    Vincent Rogier.

    Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

    Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

    OCILIB (C Driver for Oracle)

    Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle

  8. #8
    Nouveau Candidat au Club
    Inscrit en
    Février 2003
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 18
    Points : 1
    Points
    1
    Par défaut
    bon, je débute... et puis ca fait un bail que j'ai pas fait de C...


    donc j'ai lancé la compil... et là c'est le drame...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
     
     
     
    [root@fr-31-01-06-820 oracle]# gcc test_oci.c
    /tmp/ccUjMq8b.o(.text+0x27): In function `main':
    test_oci.c: undefined reference to `OCI_Initialize'
    /tmp/ccUjMq8b.o(.text+0x40):test_oci.c: undefined reference to `OCI_ConnectionCreate'
    /tmp/ccUjMq8b.o(.text+0x51):test_oci.c: undefined reference to `OCI_StatementCreate'
    /tmp/ccUjMq8b.o(.text+0x67):test_oci.c: undefined reference to `OCI_ExecuteStmt'
    /tmp/ccUjMq8b.o(.text+0x75):test_oci.c: undefined reference to `OCI_GetResultset'
    /tmp/ccUjMq8b.o(.text+0x8a):test_oci.c: undefined reference to `OCI_GetString'
    /tmp/ccUjMq8b.o(.text+0x9c):test_oci.c: undefined reference to `OCI_GetInt'
    /tmp/ccUjMq8b.o(.text+0xbc):test_oci.c: undefined reference to `OCI_FetchNext'
    /tmp/ccUjMq8b.o(.text+0xc8):test_oci.c: undefined reference to `OCI_Cleanup'
    collect2: ld a retourné 1 code d'état d'exécution

    pour l'include
    #include "ocilib.h" ,
    il faut que je fasse plutot #include "$OCILIB_SRC/ocilib.h" non?

  9. #9
    Nouveau Candidat au Club
    Inscrit en
    Février 2003
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 18
    Points : 1
    Points
    1
    Par défaut
    ne vaudrait-il pas mieux que j'utilise un makefile?

    genre celui-là
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    ALL : ocilib main.o    
    ocilib: main.o    
        gcc -o main.o -L/usr/lib/oracle/10.2.0.3/client/include/lib -lclntsh -L/usr/local/lib -locilib 
    main.o: main.c 
        gcc -Wall -o main main.c -I/usr/local/include -DOCI_IMPORT_LINKAGE -DOCI_CHARSET_UNICODE
    mais à personnaliser? par contre je ne suis pas très familier avec les makefile...

    là j'ai fait un fichier test_oci.c que je compile avec gcc test_oci.c
    Tu aurais une best practice?

    merci d'avance

  10. #10
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Points : 5 307
    Points
    5 307
    Par défaut
    "undefined reference" signifie que le code n'est pas trouvé.

    Il faut lier libocilib.so à ton prog et ajouter les flags :

    -lclntsh -locilib
    Vincent Rogier.

    Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

    Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

    OCILIB (C Driver for Oracle)

    Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle

  11. #11
    Nouveau Candidat au Club
    Inscrit en
    Février 2003
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 18
    Points : 1
    Points
    1
    Par défaut
    Je suis désolé je débute là-dedans...

    vaut-mieux -t-il que je compile en root, en oracle, en user?
    avec un makefile?

  12. #12
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Points : 5 307
    Points
    5 307
    Par défaut
    avec un makefile, c'est mieux
    et en user
    Vincent Rogier.

    Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

    Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

    OCILIB (C Driver for Oracle)

    Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle

  13. #13
    Nouveau Candidat au Club
    Inscrit en
    Février 2003
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 18
    Points : 1
    Points
    1
    Par défaut
    ok, j'ai réussi à compiler mon programme et ca marche bien :-D


    maintenant je rentre dans le vif du sujet :
    je dois faire des exports en fichiers plats de grosses requetes (plusieurs millions de lignes).
    Je l'ai fait en pro*c avec un bulk collect limit à 1000.
    Je voudrais faire la meme chose avec ocilib. Vers quoi je dois m'orienter?
    les fonctions OCI_Coll* ?
    Je n'ai pas encore trouvé d'exemple ressemblant à ce que je veux faire. Ya du bulk cen insert mais moi je dois faire du bulk collect.

    merci d'avance pour tes conseils

  14. #14
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Points : 5 307
    Points
    5 307
    Par défaut
    en fait ocilib (en interne) fait par défaut du bulk collect pour tout select (par défaut 20 lignes)...

    ensuite, dans ton app, tu fais seulement des OCI_FetchNext()...

    Pour augmenter les perfs :

    - utilise OCI_SetFetchSize(st, rows) pour augmenter la taille du bulk collect (1000 par exemple)
    - utilise OCI_SetPrefetchSize(st, rows) pour augmenter le nombre de rows prefetchés par le client oracle (500 par exemple)...
    Vincent Rogier.

    Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

    Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

    OCILIB (C Driver for Oracle)

    Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle

  15. #15
    Nouveau Candidat au Club
    Inscrit en
    Février 2003
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 18
    Points : 1
    Points
    1
    Par défaut
    Bonjour,

    donc je viens de finir mon petit programme d'extraction en fichier plat.
    Voici mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
     
    if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT))
            return EXIT_FAILURE;
     
     
        cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT);
        st = OCI_StatementCreate(cn);
     
    	OCI_SetFetchSize(st, 1000);
    	OCI_SetPrefetchSize(st, 500) ;
     
    	printf("OCI_ExecuteStmt\n");
     
    	/* table Facture */
    	OCI_ExecuteStmt(st, "select * from facture");
     
     
        printf("OCI_GetResultset\n");
    	rs = OCI_GetResultset(st);
    	printf("OCI_GetColumnCount\n");
    	n  = OCI_GetColumnCount(rs);
    	printf("%d colonnes\n", n);
    	t = time(NULL);
    	local = localtime(&t);
    	printf("Start Fetch at %s\n",asctime(local));
        /*ligne = malloc(700*sizeof(char));*/
    	/*colValue = malloc(700*sizeof(char));*/
        while (OCI_FetchNext(rs))
    	{
            /*fprintf(fSrc, "%i%s\n", OCI_GetInt(rs, 1)  , OCI_GetString(rs, 2));*/
    		cpt++;
     
    		/*printf("Fetch #%d\n",cpt);*/
     
    		for(i = 1; i <= n; i++)
    		{
    			/*printf("OCI_GetColumn %d\n", i);*/
    			col = OCI_GetColumn(rs, i);
    			/*printf("OCI_ColumnGetType\n");*/
    			typeCol = OCI_ColumnGetType(col);
    			/*printf("OCI_ColumnGetSize\n");*/
    			sizeCol = OCI_ColumnGetSize(col);
     
    			/*printf("OCI_ColumnGetSize %d\n",sizeCol);*/
     
    			/*realloc(colValue, (sizeCol+1)*sizeof(char));*/
     
    			if (OCI_IsNull(rs, i))
    			{
    				/* printf(" valeur NULL\n"); */
     
    				sprintf(format, "%%-%ds", sizeCol);
    				sprintf(colValue, format, "");
    			} else
    			{
     
    				if (typeCol == OCI_CDT_NUMERIC)
    				{
    					/*printf("type numeric\n");*/
    					sprintf(format, "%%0%dd", sizeCol);
    					/*printf("%s\n",format);*/
    					sprintf(colValue,format, OCI_GetInt(rs,i));
     
    				}
    				else if (typeCol == OCI_CDT_DATETIME)
    				{
    					 /* printf("type date\n"); */
    					dt = OCI_GetDate(rs, i);
     
    					OCI_DateToText(dt, "DDMMYYYYHH24MISS", sizeof(str)-1, str);
    					/*realloc(colValue, (20)*sizeof(char));*/
    					sprintf(format, "%%-%ds", 20);
    					/*printf("%s\n",format);*/
    					sprintf(colValue, format, str);
     
    				}
    				else if (typeCol == OCI_CDT_TEXT)
    				{
    					sprintf(format, "%%-%ds", sizeCol);
    					/*printf("%s\n",format);*/
    					sprintf(colValue, format, OCI_GetString(rs, i));
    				}
    				else 
    				{
    					printf("\n column %d unknown type\n", i);
    				}
    			}
    			/*printf("<%s>\n", colValue);*/
     
    			if (i == 1)
    				strcpy(ligne, colValue);
    			else	
    				strcat(ligne, colValue);
     
    		}	/* for col*/
     
    			fprintf(fSrc, "%s\n", ligne);	
     
     
     
     
    	}/* end of fetch*/
     
        printf("\n%d row(s) fetched\n", OCI_GetRowCount(rs));
    	printf("\n%d fetchs executes\n", cpt);
    	fclose(fSrc);
     
    	t = time(NULL);
    	local = localtime(&t);
    	printf("End at %s\n",asctime(local));
     
        OCI_Cleanup();
    D'après-vous je peux optimiser encore plus?

  16. #16
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Points : 5 307
    Points
    5 307
    Par défaut
    pour aller plus vitge, tu peux :

    - stocker avant le loop le type et la taille de chaque colone dans des tableaux afin d'éviter les appels à OCI_GetColumn()
    - augmenter les taille de fetch et prefetch
    - revoir les utilisations de sprintf

    La plus grosse partie du temps consommé réside dans le formattage de l'output avec sprintf

    les sprintf doivent au moins représenter 90% du temps consommé dans la boucle...
    Vincent Rogier.

    Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

    Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

    OCILIB (C Driver for Oracle)

    Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle

  17. #17
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Points : 5 307
    Points
    5 307
    Par défaut
    bon, j'ai compilé ton code et l'ai testé sur une table de 20 champs contenant environ 400.000 lignes sur une pauv' petite config toute naze.

    Resultats : environ 72 secondes de moyenne.

    J'ai modifié rapidement le code pour éviter certains formatage inutiles et en écrivant directement les valeurs dans le fichier.

    Résultats : environ 38 secondes de moyenne.

    De plus, le temps uniquement dédié au fetch (c'est à dire sans aucun formatage ni écriture fichier) est d'environ 8 secondes avec la boucle sur les colonnes et les OCI_GetXXX() et 5 secondes sans la boucle sur les colonnes

    Tu vois donc que le prog passe son temps en formatage..

    ps : voici le code modifié qui peut encore être nettement optimisé...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
     
    #define MAX_COLS 20
     
    int main (void)
    {
        OCI_Connection *cn  = NULL;
        OCI_Statement  *st  = NULL;
        OCI_Resultset  *rs  = NULL;
        OCI_Column     *col = NULL;
        OCI_Date       *dt  = NULL;
     
        int i, n;
     
        FILE *f = NULL;
     
        clock_t t;
     
        int y,m,d,h,mi,s;
     
        int  tab_colsize[MAX_COLS];
        int  tab_coltype[MAX_COLS];
        char tab_format[MAX_COLS][48];
        char tab_null[MAX_COLS][48];
     
        if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT))
            return EXIT_FAILURE;
     
        f = fopen("output.txt", "w");
     
        cn = OCI_ConnectionCreate("db", "usr", "pwd", OCI_SESSION_DEFAULT);
        st = OCI_StatementCreate(cn);
     
        OCI_SetFetchSize(st, 1000);
        OCI_SetPrefetchSize(st, 100);
     
        OCI_ExecuteStmt(st, "select * from test");
     
        rs = OCI_GetResultset(st);
        n  = OCI_GetColumnCount(rs);
     
        for(i = 0; i < n; i++)
        {
            col  = OCI_GetColumn(rs, i+1);
     
            tab_coltype[i] = OCI_ColumnGetType(col);
            tab_colsize[i] = OCI_ColumnGetSize(col);      
     
            if (tab_coltype[i] == OCI_CDT_NUMERIC)
            {
                sprintf(tab_format[i], "%%0%dd", tab_colsize[i]);
            }
            else if (tab_coltype[i] == OCI_CDT_DATETIME)
            {
                strcpy(tab_format[i], "%02d%02d%04d%02d%02d%02d      ");
                tab_colsize[i] = 20;
            }
            else if (tab_coltype[i] == OCI_CDT_TEXT)
            {
                sprintf(tab_format[i], "%%-%ds", tab_colsize[i]);
            }        
     
            memset(tab_null[i], ' ', 20);
       }
     
        t  = clock();
     
        while (OCI_FetchNext(rs))
        {          
            for(i = 0; i < n; i++)
            {         
                if (OCI_IsNull(rs, i+1))
                {                
                    fputs(tab_null[i], f);
                } 
                else  if (tab_coltype[i] == OCI_CDT_NUMERIC)
                {
                    fprintf(f, tab_format[i], OCI_GetInt(rs, i+1));
                }
                else if (tab_coltype[i] == OCI_CDT_DATETIME)
                {
                    dt = OCI_GetDate(rs, i+1);
     
                    OCI_DateGetDateTime(dt, &y, &m, &d, &h, &mi, &s);
     
                    fprintf(f, tab_format[i], d, m, y, h, mi, s);
                }
                else if (tab_coltype[i] == OCI_CDT_TEXT)
                {                        
                    fprintf(f, tab_format[i], OCI_GetString(rs,i+1));                    
                }
            } 
     
            fputs("\n", f);
        }
     
        printf("\n%d row(s) fetched in  %f secondes",
               OCI_GetRowCount(rs), 
               (double) (clock() - t) / (double) CLOCKS_PER_SEC);
     
        if (f)
            fclose(f);
     
     
        OCI_Cleanup();
     }
    Vincent Rogier.

    Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

    Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

    OCILIB (C Driver for Oracle)

    Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle

  18. #18
    Nouveau Candidat au Club
    Inscrit en
    Février 2003
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 18
    Points : 1
    Points
    1
    Par défaut
    Merci beaucoup.

    J'ai préféré faire les formatage en C plutot que dans le SQL (faire des TO_CHAR et des LPAD par exemple) pensant que c'était un bon choix.

    Je genere des fichiers de plusieurs Go (> 10Millions de lignes) et actuellement le temps le plus long que j'ai eu (sans utiliser tes modifs) est de 32mn pour un fichier de presque 15Go.

    Par contre je suis étonné sur une requete qui va bcp plus vite en SQL + UTL_FILE qu'avec OciLib. J'ai 35s en SQL et 12mn avec OciLib!!

    Comme tu le vois j'ai tracé l'executeStmt puis le fetch et du coup j'ai 8mn d'ExecuteStmt puis 4 minutes de fetch/ecriture.

    La requete n'est pas complexe, ce sont des jointures externes entre 4 tables.

    Est-ce normal?

  19. #19
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Points : 5 307
    Points
    5 307
    Par défaut
    Citation Envoyé par mask_hot Voir le message
    Je genere des fichiers de plusieurs Go (> 10Millions de lignes) et actuellement le temps le plus long que j'ai eu (sans utiliser tes modifs) est de 32mn pour un fichier de presque 15Go.
    Et avec la version modifiée ?

    Citation Envoyé par mask_hot Voir le message
    Par contre je suis étonné sur une requete qui va bcp plus vite en SQL + UTL_FILE qu'avec OciLib. J'ai 35s en SQL et 12mn avec OciLib!!

    Comme tu le vois j'ai tracé l'executeStmt puis le fetch et du coup j'ai 8mn d'ExecuteStmt puis 4 minutes de fetch/ecriture.

    La requete n'est pas complexe, ce sont des jointures externes entre 4 tables.

    Est-ce normal?
    ca dépend... montre le code PL/SQL et le code C...
    Vincent Rogier.

    Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

    Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

    OCILIB (C Driver for Oracle)

    Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle

  20. #20
    Nouveau Candidat au Club
    Inscrit en
    Février 2003
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 18
    Points : 1
    Points
    1
    Par défaut
    J'ai relancé avec le code modifié. Par contre il faut que je change le départ du clock si j'ai bien compris, il faut que je le mette au début du main, car là il ne mesure que le fetch.

    Sinon, le code C tu l'as.

    Voici le code PL/SQL. Dans le C c'est la meme requete sans le formattage (TO_CHAR et concaténations).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
     
    SET SERVEROUTPUT ON
    SET TIMING ON
    DECLARE                        	   
      CURSOR C0 IS   	   
      SELECT    lpad(AK.PAC_NO,10,' ')||                              
     TO_CHAR(AZ.EFT_NO,'S999999999')||           
     TO_CHAR(AZ.APB_NO,'S999999999')||                              
     lpad(AK.PAC_CAL_PAR_NO,10,' ')||                             
     lpad(AK.PAC_CAL_SIT_NO,10,' ')||
     lpad(AK.PAC_CAL_GRA_NO,10,' ')||
     lpad(to_char(AK.MOB_NO),10,' ')||                         
     TO_CHAR(AK.TTE_NO,'S999999999')||                               
     TO_CHAR(AK.LCF_NO,'S999999999')||                               
     TO_CHAR(AK.MTE_NO,'S999999999')||                              
     LPAD(AK.PAC_CODE,8,' ')|| 
     nvl(AK.PAC_ND,'          ')||                                       
     nvl(to_char(AK.PAC_SERVICE_UNIVERSEL),' ')||                                      
     lpad(nvl(TO_CHAR(AK.PAC_DATE_MS_SOUHAITEE,'YYYYMMDDhh24miss'),' '),14,' ')||         
     lpad(nvl(TO_CHAR(AK.PAC_DATE_MS_CONTRACTUELLE,'YYYYMMDDhh24miss'),' '),14,' ')||      
     lpad(nvl(TO_CHAR(AK.PAC_DATE_MS_TECHNIQUE,'YYYYMMDDhh24miss'),' '),14,' ')||          
     lpad(nvl(TO_CHAR(AK.PAC_DATE_MS_COMMERCIALE,'YYYYMMDDhh24miss'),' '),14,' ')||      
     lpad(nvl(TO_CHAR(AK.PAC_DATE_PREMIERE_FACTURATION,'YYYYMMDDhh24miss'),' '),14,' ')||                     
     lpad(nvl(TO_CHAR(AK.PAC_DATE_RESILIATION,'YYYYMMDDhh24miss'),' '),14,' ')||        
     lpad(nvl(BC.LCF_CODE,' '),30,' ')||                                            
     TO_CHAR(BD.TTC_MT_CFF,'S9999.99')||                            
     lpad(nvl(TO_CHAR(AK.PAC_DATE_RESILIATION_SVG,'YYYYMMDDhh24miss'), ' '),14,' ')||     
     AK.PAC_SU_ELIGIBLE                               
     
    FROM                                                            
           POINT_ACCES AK,       PARTENAIRE_ALIMENTATION AZ,        
           LIBELLE_CFF BC,       TYPE_TERMINAL_CFF BD               
    WHERE                                                           
     (AK.PAC_CAL_PAR_NO = AZ.PAR_NO)                                
     AND (AK.LCF_NO = BD.LCF_NO(+))                                 
     AND (AK.TTE_NO = BD.TTE_NO(+))                                 
     AND (AK.LCF_NO = BC.LCF_NO(+))                                 
    ;
      TYPE T_LINE IS TABLE OF VARCHAR2(258);
      V_LINE T_LINE; 
      V_NLINE VARCHAR2(32767);
      V_ANNEE VARCHAR2(4);
      F1 UTL_FILE.FILE_TYPE; 
      N_LIG NUMBER;
    BEGIN
      DBMS_OUTPUT.PUT_LINE('DATE DEB : '||TO_CHAR(SYSDATE,'DD/MM/YY HH:MI:SS'));
     
      F1 := UTL_FILE.FOPEN('/home/oracle/test_pl/','rppac05.txt','w'); 
      N_LIG := 0;
      V_NLINE:='';
     
         OPEN C0;
        LOOP
          --V_LINE := '';
          FETCH C0 BULK COLLECT INTO V_LINE LIMIT 127;
          EXIT WHEN C0%NOTFOUND;
          FOR I IN V_LINE.FIRST .. V_LINE.LAST LOOP
             V_NLINE := V_NLINE||V_LINE(i)||'\n';
          END LOOP;
          UTL_FILE.PUTF(F1, V_NLINE);
          V_NLINE:='';
        END LOOP;
        CLOSE C0; 
     
      UTL_FILE.FCLOSE(F1); 
      DBMS_OUTPUT.PUT_LINE('DATE FIN : '||TO_CHAR(SYSDATE,'DD/MM/YY HH:MI:SS'));
    END;
    /

Discussions similaires

  1. [OCILIB] Problème de compilation avec code::blocks
    Par dbqg7322 dans le forum Interfaces de programmation
    Réponses: 2
    Dernier message: 11/01/2013, 14h21
  2. problème de compil devc++ socket
    Par stefdem dans le forum Autres éditeurs
    Réponses: 2
    Dernier message: 11/12/2003, 12h33
  3. Réponses: 1
    Dernier message: 29/10/2003, 13h16
  4. Problème de compilation de la DLL du XMLRad
    Par [DreaMs] dans le forum XMLRAD
    Réponses: 2
    Dernier message: 16/04/2003, 17h46
  5. Réponses: 1
    Dernier message: 27/05/2002, 02h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo