OVH Cloud OVH Cloud

T-SQL

8 réponses
Avatar
MB
Bonjour
Je sort d'une formation et le discours était
Bannir les procèdures stokées
Bannir les select *

Nous n'avons pas encore poussé nos tests très loin mais pour l'instant les
curseurs vont plus vite et les select * aussi !

voilà la méthode que l'on a utilisé
- voici un lien qui vous dira comment éviter les curseurs:
http://sqlpro.developpez.com/cours/sqlserver/MSSQLServer_avoidCursor/



et voilà note test

Avec curseur


DECLARE @nvc_PRE_IDE nvarchar(150)
DECLARE @nvc_NOM_IDE nvarchar(150)
DECLARE @nvc_PAT_NOM_JF nvarchar(150)
DECLARE @nvc_DEBUT_NOM nvarchar(10)
DECLARE @int_PAT_SEXE int
DECLARE @int_PAT_NAI_JJ int
DECLARE @int_PAT_NAI_MM int
DECLARE @int_PAT_NAI_AA int
DECLARE @int_IDE_CLE int


DECLARE @nvc_USG_CLE nvarchar(150)
DECLARE @cpt int


--- ----------------------------------------------------------------------------------------------------------
--- On efface les anciens enregistrements de la base

DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
WHERE USG_CLE = @nvc_USG_CLE

SELECT
@cpt = count(*)
FROM TMP_TAB_REC_DOUBLONS_DS_BASE

IF @cpt = 0
BEGIN
TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE
END

SET @cpt = 0

--- ----------------------------------------------------------------------------------------------------------
--- ----------------------------------------------------------------------------------------------------------
--- Ouverture du curseur de parcours des enregistrements

DECLARE cur_CleIdentite CURSOR
FOR
SELECT
CLE_IDE
FROM ADR_TAB_IDENTITES
ORDER BY CLE_IDE

OPEN cur_CleIdentite

FETCH NEXT FROM cur_CleIdentite
INTO @int_IDE_CLE

WHILE @@FETCH_STATUS = 0
begin


--- ***************************************************
--- Corps du programme
SET @cpt = @cpt + 1
--- ********************************************************



FETCH NEXT FROM cur_CleIdentite
INTO @int_IDE_CLE
End

--- fermeture du curseur

Close cur_CleIdentite
DEALLOCATE cur_CleIdentite

print @cpt


___________________________________________________________________________________________


SANS CURSOR


DECLARE @nvc_PRE_IDE nvarchar(150)
DECLARE @nvc_PRE_IDE nvarchar(150);
DECLARE @nvc_NOM_IDE nvarchar(150);
DECLARE @nvc_PAT_NOM_JF nvarchar(150);
DECLARE @nvc_DEBUT_NOM nvarchar(10);
DECLARE @int_PAT_SEXE int;
DECLARE @int_PAT_NAI_JJ int;
DECLARE @int_PAT_NAI_MM int;
DECLARE @int_PAT_NAI_AA int;
DECLARE @int_IDE_CLE int;
DECLARE @cpt int;


--- ----------------------------------------------------------------------------------------------------------
--- On efface les anciens enregistrements de la base

DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
WHERE USG_CLE = @nvc_USG_CLE;

SELECT
@cpt = count(*)
FROM TMP_TAB_REC_DOUBLONS_DS_BASE;


IF @cpt = 0
BEGIN
TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE;
END;


SET @cpt = 0;

--- ----------------------------------------------------------------------------------------------------------
--- ----------------------------------------------------------------------------------------------------------
--- On stocke les clé des identités dans une table temporaire

SELECT
CLE_IDE,
0 AS OK
INTO #TMP_CLE_IDE
FROM ADR_TAB_IDENTITES
ORDER BY CLE_IDE;

-- tant qu'il y a au moins une table à traiter
WHILE EXISTS(
SELECT
CLE_IDE
FROM #TMP_CLE_IDE
WHERE OK = 0)
BEGIN

-- prendre la clé de la première identité à traiter
SET @int_IDE_CLE = ( SELECT TOP 1 CLE_IDE
FROM #TMP_CLE_IDE WHERE OK = 0
ORDER BY 1);


---
********************************************************************
--- Corps du programme
SET @cpt = @cpt + 1

---
********************************************************************




-- flaguer l'objet traité dans la table des objets à traiter
UPDATE #TMP_CLE_IDE
SET OK = 1
WHERE CLE_IDE = @int_IDE_CLE;

--- Fin de la boucle WHILE
END;


-- supprimez la table temporaire de traitement
DROP TABLE #TMP_CLE_IDE;

print @cpt


voilou

8 réponses

Avatar
Patrice
Tu veux dire sans doute bannir les "curseurs" et non pas les "procédures
stockées" ?

Ta procédure stockée fait également un traitement procédural ce qui est sans
doute le problème. Ce n'est pas à proprement parler les "curseurs" qui sont
à "éviter" mais plutôt le traitement "procédural" par opposition aux
traitements ensemblistes...

Quel est ce fameux traitement ? N'est il pas réalisable avec une instruction
SQL unique... Pour l'instant à part le flag et le comptage je ne vois pas
trop ce que tu cherches à faire...

Après il y a des cas où tu es sans doute obligé...

--
Patrice

"MB" a écrit dans le message de
news:e8NlcD%23%
Bonjour
Je sort d'une formation et le discours était
Bannir les procèdures stokées
Bannir les select *

Nous n'avons pas encore poussé nos tests très loin mais pour l'instant les
curseurs vont plus vite et les select * aussi !

voilà la méthode que l'on a utilisé
- voici un lien qui vous dira comment éviter les curseurs:
http://sqlpro.developpez.com/cours/sqlserver/MSSQLServer_avoidCursor/



et voilà note test

Avec curseur


DECLARE @nvc_PRE_IDE nvarchar(150)
DECLARE @nvc_NOM_IDE nvarchar(150)
DECLARE @nvc_PAT_NOM_JF nvarchar(150)
DECLARE @nvc_DEBUT_NOM nvarchar(10)
DECLARE @int_PAT_SEXE int
DECLARE @int_PAT_NAI_JJ int
DECLARE @int_PAT_NAI_MM int
DECLARE @int_PAT_NAI_AA int
DECLARE @int_IDE_CLE int


DECLARE @nvc_USG_CLE nvarchar(150)
DECLARE @cpt int


--- ----------------------------------------------------------------------


------------------------------------
--- On efface les anciens enregistrements de la base

DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
WHERE USG_CLE = @nvc_USG_CLE

SELECT
@cpt = count(*)
FROM TMP_TAB_REC_DOUBLONS_DS_BASE

IF @cpt = 0
BEGIN
TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE
END

SET @cpt = 0

--- ----------------------------------------------------------------------


------------------------------------
--- ----------------------------------------------------------------------


------------------------------------
--- Ouverture du curseur de parcours des enregistrements

DECLARE cur_CleIdentite CURSOR
FOR
SELECT
CLE_IDE
FROM ADR_TAB_IDENTITES
ORDER BY CLE_IDE

OPEN cur_CleIdentite

FETCH NEXT FROM cur_CleIdentite
INTO @int_IDE_CLE

WHILE @@FETCH_STATUS = 0
begin


--- ***************************************************
--- Corps du programme
SET @cpt = @cpt + 1
--- ********************************************************



FETCH NEXT FROM cur_CleIdentite
INTO @int_IDE_CLE
End

--- fermeture du curseur

Close cur_CleIdentite
DEALLOCATE cur_CleIdentite

print @cpt





____________________________________________________________________________
_______________


SANS CURSOR


DECLARE @nvc_PRE_IDE nvarchar(150)
DECLARE @nvc_PRE_IDE nvarchar(150);
DECLARE @nvc_NOM_IDE nvarchar(150);
DECLARE @nvc_PAT_NOM_JF nvarchar(150);
DECLARE @nvc_DEBUT_NOM nvarchar(10);
DECLARE @int_PAT_SEXE int;
DECLARE @int_PAT_NAI_JJ int;
DECLARE @int_PAT_NAI_MM int;
DECLARE @int_PAT_NAI_AA int;
DECLARE @int_IDE_CLE int;
DECLARE @cpt int;


--- ----------------------------------------------------------------------


------------------------------------
--- On efface les anciens enregistrements de la base

DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
WHERE USG_CLE = @nvc_USG_CLE;

SELECT
@cpt = count(*)
FROM TMP_TAB_REC_DOUBLONS_DS_BASE;


IF @cpt = 0
BEGIN
TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE;
END;


SET @cpt = 0;

--- ----------------------------------------------------------------------


------------------------------------
--- ----------------------------------------------------------------------


------------------------------------
--- On stocke les clé des identités dans une table temporaire

SELECT
CLE_IDE,
0 AS OK
INTO #TMP_CLE_IDE
FROM ADR_TAB_IDENTITES
ORDER BY CLE_IDE;

-- tant qu'il y a au moins une table à traiter
WHILE EXISTS(
SELECT
CLE_IDE
FROM #TMP_CLE_IDE
WHERE OK = 0)
BEGIN

-- prendre la clé de la première identité à traiter
SET @int_IDE_CLE = ( SELECT TOP 1 CLE_IDE
FROM #TMP_CLE_IDE WHERE OK = 0
ORDER BY 1);


---
********************************************************************
--- Corps du programme
SET @cpt = @cpt + 1

---
********************************************************************




-- flaguer l'objet traité dans la table des objets à traiter
UPDATE #TMP_CLE_IDE
SET OK = 1
WHERE CLE_IDE = @int_IDE_CLE;

--- Fin de la boucle WHILE
END;


-- supprimez la table temporaire de traitement
DROP TABLE #TMP_CLE_IDE;

print @cpt


voilou






Avatar
MB
Pour vous répondre, dans la boucle il y a gros traitement sur du contôle de
données avec beaucoup if if if if ....

Pour le test, nous avons dans un premier temps supprimé tous les if if if
if .... et comparé que les boucles sur le jeu de données avec et sans
curseur. C'est le curseur le plus rapide avec 1 minute de moins sur 8000
enregistrements.


"Patrice" a écrit dans le message de news:
%23dzFYb%23%
Tu veux dire sans doute bannir les "curseurs" et non pas les "procédures
stockées" ?

Ta procédure stockée fait également un traitement procédural ce qui est
sans
doute le problème. Ce n'est pas à proprement parler les "curseurs" qui
sont
à "éviter" mais plutôt le traitement "procédural" par opposition aux
traitements ensemblistes...

Quel est ce fameux traitement ? N'est il pas réalisable avec une
instruction
SQL unique... Pour l'instant à part le flag et le comptage je ne vois pas
trop ce que tu cherches à faire...

Après il y a des cas où tu es sans doute obligé...

--
Patrice

"MB" a écrit dans le message de
news:e8NlcD%23%
Bonjour
Je sort d'une formation et le discours était
Bannir les procèdures stokées
Bannir les select *

Nous n'avons pas encore poussé nos tests très loin mais pour l'instant
les
curseurs vont plus vite et les select * aussi !

voilà la méthode que l'on a utilisé
- voici un lien qui vous dira comment éviter les curseurs:
http://sqlpro.developpez.com/cours/sqlserver/MSSQLServer_avoidCursor/



et voilà note test

Avec curseur


DECLARE @nvc_PRE_IDE nvarchar(150)
DECLARE @nvc_NOM_IDE nvarchar(150)
DECLARE @nvc_PAT_NOM_JF nvarchar(150)
DECLARE @nvc_DEBUT_NOM nvarchar(10)
DECLARE @int_PAT_SEXE int
DECLARE @int_PAT_NAI_JJ int
DECLARE @int_PAT_NAI_MM int
DECLARE @int_PAT_NAI_AA int
DECLARE @int_IDE_CLE int


DECLARE @nvc_USG_CLE nvarchar(150)
DECLARE @cpt int


--- ----------------------------------------------------------------------


------------------------------------
--- On efface les anciens enregistrements de la base

DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
WHERE USG_CLE = @nvc_USG_CLE

SELECT
@cpt = count(*)
FROM TMP_TAB_REC_DOUBLONS_DS_BASE

IF @cpt = 0
BEGIN
TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE
END

SET @cpt = 0

--- ----------------------------------------------------------------------


------------------------------------
--- ----------------------------------------------------------------------


------------------------------------
--- Ouverture du curseur de parcours des enregistrements

DECLARE cur_CleIdentite CURSOR
FOR
SELECT
CLE_IDE
FROM ADR_TAB_IDENTITES
ORDER BY CLE_IDE

OPEN cur_CleIdentite

FETCH NEXT FROM cur_CleIdentite
INTO @int_IDE_CLE

WHILE @@FETCH_STATUS = 0
begin


--- ***************************************************
--- Corps du programme
SET @cpt = @cpt + 1
--- ********************************************************



FETCH NEXT FROM cur_CleIdentite
INTO @int_IDE_CLE
End

--- fermeture du curseur

Close cur_CleIdentite
DEALLOCATE cur_CleIdentite

print @cpt





____________________________________________________________________________
_______________


SANS CURSOR


DECLARE @nvc_PRE_IDE nvarchar(150)
DECLARE @nvc_PRE_IDE nvarchar(150);
DECLARE @nvc_NOM_IDE nvarchar(150);
DECLARE @nvc_PAT_NOM_JF nvarchar(150);
DECLARE @nvc_DEBUT_NOM nvarchar(10);
DECLARE @int_PAT_SEXE int;
DECLARE @int_PAT_NAI_JJ int;
DECLARE @int_PAT_NAI_MM int;
DECLARE @int_PAT_NAI_AA int;
DECLARE @int_IDE_CLE int;
DECLARE @cpt int;


--- ----------------------------------------------------------------------


------------------------------------
--- On efface les anciens enregistrements de la base

DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
WHERE USG_CLE = @nvc_USG_CLE;

SELECT
@cpt = count(*)
FROM TMP_TAB_REC_DOUBLONS_DS_BASE;


IF @cpt = 0
BEGIN
TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE;
END;


SET @cpt = 0;

--- ----------------------------------------------------------------------


------------------------------------
--- ----------------------------------------------------------------------


------------------------------------
--- On stocke les clé des identités dans une table temporaire

SELECT
CLE_IDE,
0 AS OK
INTO #TMP_CLE_IDE
FROM ADR_TAB_IDENTITES
ORDER BY CLE_IDE;

-- tant qu'il y a au moins une table à traiter
WHILE EXISTS(
SELECT
CLE_IDE
FROM #TMP_CLE_IDE
WHERE OK = 0)
BEGIN

-- prendre la clé de la première identité à traiter
SET @int_IDE_CLE = ( SELECT TOP 1 CLE_IDE
FROM #TMP_CLE_IDE WHERE OK = 0
ORDER BY 1);


---
********************************************************************
--- Corps du programme
SET @cpt = @cpt + 1

---
********************************************************************




-- flaguer l'objet traité dans la table des objets à traiter
UPDATE #TMP_CLE_IDE
SET OK = 1
WHERE CLE_IDE = @int_IDE_CLE;

--- Fin de la boucle WHILE
END;


-- supprimez la table temporaire de traitement
DROP TABLE #TMP_CLE_IDE;

print @cpt


voilou










Avatar
Med Bouchenafa
Ce n'est pas en évitant le mot CURSEUR que l'on évite les curseurs.
Tout traitement itératif est un curseur et un WHILE est un curseur aussi.

La différence entre un SELECT * et un SELECT NomColonne n'est flagrante que
sur de la volumétrie et un indexage adéquat

--
Bien cordialement
Med Bouchenafa

"MB" wrote in message
news:e8NlcD##
Bonjour
Je sort d'une formation et le discours était
Bannir les procèdures stokées
Bannir les select *

Nous n'avons pas encore poussé nos tests très loin mais pour l'instant les
curseurs vont plus vite et les select * aussi !

voilà la méthode que l'on a utilisé
- voici un lien qui vous dira comment éviter les curseurs:
http://sqlpro.developpez.com/cours/sqlserver/MSSQLServer_avoidCursor/



et voilà note test

Avec curseur


DECLARE @nvc_PRE_IDE nvarchar(150)
DECLARE @nvc_NOM_IDE nvarchar(150)
DECLARE @nvc_PAT_NOM_JF nvarchar(150)
DECLARE @nvc_DEBUT_NOM nvarchar(10)
DECLARE @int_PAT_SEXE int
DECLARE @int_PAT_NAI_JJ int
DECLARE @int_PAT_NAI_MM int
DECLARE @int_PAT_NAI_AA int
DECLARE @int_IDE_CLE int


DECLARE @nvc_USG_CLE nvarchar(150)
DECLARE @cpt int


--- ----------------------------------------------------------------------


------------------------------------
--- On efface les anciens enregistrements de la base

DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
WHERE USG_CLE = @nvc_USG_CLE

SELECT
@cpt = count(*)
FROM TMP_TAB_REC_DOUBLONS_DS_BASE

IF @cpt = 0
BEGIN
TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE
END

SET @cpt = 0

--- ----------------------------------------------------------------------


------------------------------------
--- ----------------------------------------------------------------------


------------------------------------
--- Ouverture du curseur de parcours des enregistrements

DECLARE cur_CleIdentite CURSOR
FOR
SELECT
CLE_IDE
FROM ADR_TAB_IDENTITES
ORDER BY CLE_IDE

OPEN cur_CleIdentite

FETCH NEXT FROM cur_CleIdentite
INTO @int_IDE_CLE

WHILE @@FETCH_STATUS = 0
begin


--- ***************************************************
--- Corps du programme
SET @cpt = @cpt + 1
--- ********************************************************



FETCH NEXT FROM cur_CleIdentite
INTO @int_IDE_CLE
End

--- fermeture du curseur

Close cur_CleIdentite
DEALLOCATE cur_CleIdentite

print @cpt





____________________________________________________________________________
_______________


SANS CURSOR


DECLARE @nvc_PRE_IDE nvarchar(150)
DECLARE @nvc_PRE_IDE nvarchar(150);
DECLARE @nvc_NOM_IDE nvarchar(150);
DECLARE @nvc_PAT_NOM_JF nvarchar(150);
DECLARE @nvc_DEBUT_NOM nvarchar(10);
DECLARE @int_PAT_SEXE int;
DECLARE @int_PAT_NAI_JJ int;
DECLARE @int_PAT_NAI_MM int;
DECLARE @int_PAT_NAI_AA int;
DECLARE @int_IDE_CLE int;
DECLARE @cpt int;


--- ----------------------------------------------------------------------


------------------------------------
--- On efface les anciens enregistrements de la base

DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
WHERE USG_CLE = @nvc_USG_CLE;

SELECT
@cpt = count(*)
FROM TMP_TAB_REC_DOUBLONS_DS_BASE;


IF @cpt = 0
BEGIN
TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE;
END;


SET @cpt = 0;

--- ----------------------------------------------------------------------


------------------------------------
--- ----------------------------------------------------------------------


------------------------------------
--- On stocke les clé des identités dans une table temporaire

SELECT
CLE_IDE,
0 AS OK
INTO #TMP_CLE_IDE
FROM ADR_TAB_IDENTITES
ORDER BY CLE_IDE;

-- tant qu'il y a au moins une table à traiter
WHILE EXISTS(
SELECT
CLE_IDE
FROM #TMP_CLE_IDE
WHERE OK = 0)
BEGIN

-- prendre la clé de la première identité à traiter
SET @int_IDE_CLE = ( SELECT TOP 1 CLE_IDE
FROM #TMP_CLE_IDE WHERE OK = 0
ORDER BY 1);


---
********************************************************************
--- Corps du programme
SET @cpt = @cpt + 1

---
********************************************************************




-- flaguer l'objet traité dans la table des objets à traiter
UPDATE #TMP_CLE_IDE
SET OK = 1
WHERE CLE_IDE = @int_IDE_CLE;

--- Fin de la boucle WHILE
END;


-- supprimez la table temporaire de traitement
DROP TABLE #TMP_CLE_IDE;

print @cpt


voilou






Avatar
Patrice
Ce traitement peut-il être mis sous forme ensembliste (par exemple CASE) ?

Si on est *obligé* de parcourir séquentiellement les lignes d'une table, le
curseur sera plus rapide qu'un parcours simulé à base de boucles et
d'instructions SQL...

Donc le cas d'école que tu as plus haut, tu peux te passer d'une boucle, la
vraie comparaison serait donc plutôt avec un simple
UPDATE MaTable SET UneColonne=MonRésultat

Disons que pour être plus précis, la recommandation que voulait transmettre
le formateur est de choisir toujours un traitement "ensembliste" par rapport
à un parcours séquentiel explicite des données (et dans ce cas un CURSOR
peut être la meilleure solution).
--
Patrice

"MB" a écrit dans le message de
news:OzJYvU$%
Pour vous répondre, dans la boucle il y a gros traitement sur du contôle


de
données avec beaucoup if if if if ....

Pour le test, nous avons dans un premier temps supprimé tous les if if if
if .... et comparé que les boucles sur le jeu de données avec et sans
curseur. C'est le curseur le plus rapide avec 1 minute de moins sur 8000
enregistrements.


"Patrice" a écrit dans le message de news:
%23dzFYb%23%
> Tu veux dire sans doute bannir les "curseurs" et non pas les "procédures
> stockées" ?
>
> Ta procédure stockée fait également un traitement procédural ce qui est
> sans
> doute le problème. Ce n'est pas à proprement parler les "curseurs" qui
> sont
> à "éviter" mais plutôt le traitement "procédural" par opposition aux
> traitements ensemblistes...
>
> Quel est ce fameux traitement ? N'est il pas réalisable avec une
> instruction
> SQL unique... Pour l'instant à part le flag et le comptage je ne vois


pas
> trop ce que tu cherches à faire...
>
> Après il y a des cas où tu es sans doute obligé...
>
> --
> Patrice
>
> "MB" a écrit dans le message de
> news:e8NlcD%23%
>> Bonjour
>> Je sort d'une formation et le discours était
>> Bannir les procèdures stokées
>> Bannir les select *
>>
>> Nous n'avons pas encore poussé nos tests très loin mais pour l'instant
>> les
>> curseurs vont plus vite et les select * aussi !
>>
>> voilà la méthode que l'on a utilisé
>> - voici un lien qui vous dira comment éviter les curseurs:
>> http://sqlpro.developpez.com/cours/sqlserver/MSSQLServer_avoidCursor/
>>
>>
>>
>> et voilà note test
>>
>> Avec curseur
>>
>>
>> DECLARE @nvc_PRE_IDE nvarchar(150)
>> DECLARE @nvc_NOM_IDE nvarchar(150)
>> DECLARE @nvc_PAT_NOM_JF nvarchar(150)
>> DECLARE @nvc_DEBUT_NOM nvarchar(10)
>> DECLARE @int_PAT_SEXE int
>> DECLARE @int_PAT_NAI_JJ int
>> DECLARE @int_PAT_NAI_MM int
>> DECLARE @int_PAT_NAI_AA int
>> DECLARE @int_IDE_CLE int
>>
>>
>> DECLARE @nvc_USG_CLE nvarchar(150)
>> DECLARE @cpt int
>>
>>

--- ---------------------------------------------------------------------




-
> ------------------------------------
>> --- On efface les anciens enregistrements de la base
>>
>> DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
>> WHERE USG_CLE = @nvc_USG_CLE
>>
>> SELECT
>> @cpt = count(*)
>> FROM TMP_TAB_REC_DOUBLONS_DS_BASE
>>
>> IF @cpt = 0
>> BEGIN
>> TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE
>> END
>>
>> SET @cpt = 0
>>

--- ---------------------------------------------------------------------




-
> ------------------------------------

--- ---------------------------------------------------------------------




-
> ------------------------------------
>> --- Ouverture du curseur de parcours des enregistrements
>>
>> DECLARE cur_CleIdentite CURSOR
>> FOR
>> SELECT
>> CLE_IDE
>> FROM ADR_TAB_IDENTITES
>> ORDER BY CLE_IDE
>>
>> OPEN cur_CleIdentite
>>
>> FETCH NEXT FROM cur_CleIdentite
>> INTO @int_IDE_CLE
>>
>> WHILE @@FETCH_STATUS = 0
>> begin
>>
>>
>> --- ***************************************************
>> --- Corps du programme
>> SET @cpt = @cpt + 1
>> --- ********************************************************
>>
>>
>>
>> FETCH NEXT FROM cur_CleIdentite
>> INTO @int_IDE_CLE
>> End
>>
>> --- fermeture du curseur
>>
>> Close cur_CleIdentite
>> DEALLOCATE cur_CleIdentite
>>
>> print @cpt
>>
>>
>>
>


____________________________________________________________________________
> _______________
>>
>>
>> SANS CURSOR
>>
>>
>> DECLARE @nvc_PRE_IDE nvarchar(150)
>> DECLARE @nvc_PRE_IDE nvarchar(150);
>> DECLARE @nvc_NOM_IDE nvarchar(150);
>> DECLARE @nvc_PAT_NOM_JF nvarchar(150);
>> DECLARE @nvc_DEBUT_NOM nvarchar(10);
>> DECLARE @int_PAT_SEXE int;
>> DECLARE @int_PAT_NAI_JJ int;
>> DECLARE @int_PAT_NAI_MM int;
>> DECLARE @int_PAT_NAI_AA int;
>> DECLARE @int_IDE_CLE int;
>> DECLARE @cpt int;
>>
>>

--- ---------------------------------------------------------------------




-
> ------------------------------------
>> --- On efface les anciens enregistrements de la base
>>
>> DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
>> WHERE USG_CLE = @nvc_USG_CLE;
>>
>> SELECT
>> @cpt = count(*)
>> FROM TMP_TAB_REC_DOUBLONS_DS_BASE;
>>
>>
>> IF @cpt = 0
>> BEGIN
>> TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE;
>> END;
>>
>>
>> SET @cpt = 0;
>>

--- ---------------------------------------------------------------------




-
> ------------------------------------

--- ---------------------------------------------------------------------




-
> ------------------------------------
>> --- On stocke les clé des identités dans une table temporaire
>>
>> SELECT
>> CLE_IDE,
>> 0 AS OK
>> INTO #TMP_CLE_IDE
>> FROM ADR_TAB_IDENTITES
>> ORDER BY CLE_IDE;
>>
>> -- tant qu'il y a au moins une table à traiter
>> WHILE EXISTS(
>> SELECT
>> CLE_IDE
>> FROM #TMP_CLE_IDE
>> WHERE OK = 0)
>> BEGIN
>>
>> -- prendre la clé de la première identité à traiter
>> SET @int_IDE_CLE = ( SELECT TOP 1 CLE_IDE
>> FROM #TMP_CLE_IDE WHERE OK = 0
>> ORDER BY 1);
>>
>>
>> ---
>> ********************************************************************
>> --- Corps du programme
>> SET @cpt = @cpt + 1
>>
>> ---
>> ********************************************************************
>>
>>
>>
>>
>> -- flaguer l'objet traité dans la table des objets à traiter
>> UPDATE #TMP_CLE_IDE
>> SET OK = 1
>> WHERE CLE_IDE = @int_IDE_CLE;
>>
>> --- Fin de la boucle WHILE
>> END;
>>
>>
>> -- supprimez la table temporaire de traitement
>> DROP TABLE #TMP_CLE_IDE;
>>
>> print @cpt
>>
>>
>> voilou
>>
>>
>>
>>
>
>




Avatar
MB
Dans quel cas on est dans de la programmation *ensembliste*
Merci

"Patrice" a écrit dans le message de news:
eG1Pwy$%
Ce traitement peut-il être mis sous forme ensembliste (par exemple CASE) ?

Si on est *obligé* de parcourir séquentiellement les lignes d'une table,
le
curseur sera plus rapide qu'un parcours simulé à base de boucles et
d'instructions SQL...

Donc le cas d'école que tu as plus haut, tu peux te passer d'une boucle,
la
vraie comparaison serait donc plutôt avec un simple
UPDATE MaTable SET UneColonne=MonRésultat

Disons que pour être plus précis, la recommandation que voulait
transmettre
le formateur est de choisir toujours un traitement "ensembliste" par
rapport
à un parcours séquentiel explicite des données (et dans ce cas un CURSOR
peut être la meilleure solution).
--
Patrice

"MB" a écrit dans le message de
news:OzJYvU$%
Pour vous répondre, dans la boucle il y a gros traitement sur du contôle


de
données avec beaucoup if if if if ....

Pour le test, nous avons dans un premier temps supprimé tous les if if
if
if .... et comparé que les boucles sur le jeu de données avec et sans
curseur. C'est le curseur le plus rapide avec 1 minute de moins sur 8000
enregistrements.


"Patrice" a écrit dans le message de news:
%23dzFYb%23%
> Tu veux dire sans doute bannir les "curseurs" et non pas les
> "procédures
> stockées" ?
>
> Ta procédure stockée fait également un traitement procédural ce qui est
> sans
> doute le problème. Ce n'est pas à proprement parler les "curseurs" qui
> sont
> à "éviter" mais plutôt le traitement "procédural" par opposition aux
> traitements ensemblistes...
>
> Quel est ce fameux traitement ? N'est il pas réalisable avec une
> instruction
> SQL unique... Pour l'instant à part le flag et le comptage je ne vois


pas
> trop ce que tu cherches à faire...
>
> Après il y a des cas où tu es sans doute obligé...
>
> --
> Patrice
>
> "MB" a écrit dans le message de
> news:e8NlcD%23%
>> Bonjour
>> Je sort d'une formation et le discours était
>> Bannir les procèdures stokées
>> Bannir les select *
>>
>> Nous n'avons pas encore poussé nos tests très loin mais pour l'instant
>> les
>> curseurs vont plus vite et les select * aussi !
>>
>> voilà la méthode que l'on a utilisé
>> - voici un lien qui vous dira comment éviter les curseurs:
>> http://sqlpro.developpez.com/cours/sqlserver/MSSQLServer_avoidCursor/
>>
>>
>>
>> et voilà note test
>>
>> Avec curseur
>>
>>
>> DECLARE @nvc_PRE_IDE nvarchar(150)
>> DECLARE @nvc_NOM_IDE nvarchar(150)
>> DECLARE @nvc_PAT_NOM_JF nvarchar(150)
>> DECLARE @nvc_DEBUT_NOM nvarchar(10)
>> DECLARE @int_PAT_SEXE int
>> DECLARE @int_PAT_NAI_JJ int
>> DECLARE @int_PAT_NAI_MM int
>> DECLARE @int_PAT_NAI_AA int
>> DECLARE @int_IDE_CLE int
>>
>>
>> DECLARE @nvc_USG_CLE nvarchar(150)
>> DECLARE @cpt int
>>
>>

--- ---------------------------------------------------------------------




-
> ------------------------------------
>> --- On efface les anciens enregistrements de la base
>>
>> DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
>> WHERE USG_CLE = @nvc_USG_CLE
>>
>> SELECT
>> @cpt = count(*)
>> FROM TMP_TAB_REC_DOUBLONS_DS_BASE
>>
>> IF @cpt = 0
>> BEGIN
>> TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE
>> END
>>
>> SET @cpt = 0
>>

--- ---------------------------------------------------------------------




-
> ------------------------------------

--- ---------------------------------------------------------------------




-
> ------------------------------------
>> --- Ouverture du curseur de parcours des enregistrements
>>
>> DECLARE cur_CleIdentite CURSOR
>> FOR
>> SELECT
>> CLE_IDE
>> FROM ADR_TAB_IDENTITES
>> ORDER BY CLE_IDE
>>
>> OPEN cur_CleIdentite
>>
>> FETCH NEXT FROM cur_CleIdentite
>> INTO @int_IDE_CLE
>>
>> WHILE @@FETCH_STATUS = 0
>> begin
>>
>>
>> --- ***************************************************
>> --- Corps du programme
>> SET @cpt = @cpt + 1
>> --- ********************************************************
>>
>>
>>
>> FETCH NEXT FROM cur_CleIdentite
>> INTO @int_IDE_CLE
>> End
>>
>> --- fermeture du curseur
>>
>> Close cur_CleIdentite
>> DEALLOCATE cur_CleIdentite
>>
>> print @cpt
>>
>>
>>
>


____________________________________________________________________________
> _______________
>>
>>
>> SANS CURSOR
>>
>>
>> DECLARE @nvc_PRE_IDE nvarchar(150)
>> DECLARE @nvc_PRE_IDE nvarchar(150);
>> DECLARE @nvc_NOM_IDE nvarchar(150);
>> DECLARE @nvc_PAT_NOM_JF nvarchar(150);
>> DECLARE @nvc_DEBUT_NOM nvarchar(10);
>> DECLARE @int_PAT_SEXE int;
>> DECLARE @int_PAT_NAI_JJ int;
>> DECLARE @int_PAT_NAI_MM int;
>> DECLARE @int_PAT_NAI_AA int;
>> DECLARE @int_IDE_CLE int;
>> DECLARE @cpt int;
>>
>>

--- ---------------------------------------------------------------------




-
> ------------------------------------
>> --- On efface les anciens enregistrements de la base
>>
>> DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
>> WHERE USG_CLE = @nvc_USG_CLE;
>>
>> SELECT
>> @cpt = count(*)
>> FROM TMP_TAB_REC_DOUBLONS_DS_BASE;
>>
>>
>> IF @cpt = 0
>> BEGIN
>> TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE;
>> END;
>>
>>
>> SET @cpt = 0;
>>

--- ---------------------------------------------------------------------




-
> ------------------------------------

--- ---------------------------------------------------------------------




-
> ------------------------------------
>> --- On stocke les clé des identités dans une table temporaire
>>
>> SELECT
>> CLE_IDE,
>> 0 AS OK
>> INTO #TMP_CLE_IDE
>> FROM ADR_TAB_IDENTITES
>> ORDER BY CLE_IDE;
>>
>> -- tant qu'il y a au moins une table à traiter
>> WHILE EXISTS(
>> SELECT
>> CLE_IDE
>> FROM #TMP_CLE_IDE
>> WHERE OK = 0)
>> BEGIN
>>
>> -- prendre la clé de la première identité à traiter
>> SET @int_IDE_CLE = ( SELECT TOP 1 CLE_IDE
>> FROM #TMP_CLE_IDE WHERE OK = 0
>> ORDER BY 1);
>>
>>
>> ---
>> ********************************************************************
>> --- Corps du programme
>> SET @cpt = @cpt + 1
>>
>> ---
>> ********************************************************************
>>
>>
>>
>>
>> -- flaguer l'objet traité dans la table des objets à traiter
>> UPDATE #TMP_CLE_IDE
>> SET OK = 1
>> WHERE CLE_IDE = @int_IDE_CLE;
>>
>> --- Fin de la boucle WHILE
>> END;
>>
>>
>> -- supprimez la table temporaire de traitement
>> DROP TABLE #TMP_CLE_IDE;
>>
>> print @cpt
>>
>>
>> voilou
>>
>>
>>
>>
>
>








Avatar
Fred BROUARD
bonjour,

MB a écrit:
Dans quel cas on est dans de la programmation *ensembliste*
Merci



1) lorsque TOUT le traitement est fait à l'aide d'une seule et unique requête
(UPDATE, INSERT, DELETE ou SELECT)

2) lorsqu'il y a une requête encapsulant des vues ou des expressions de table (CTE)

3) lorsque le code n'a aucun branchement : notamment dans le cas de requêtes SQL
enchaînées pour des mises à jour combinées (par exemple table fille + table mère).

Sinon, effectivement l'exemple choisit pour comparaison n'a pas de réel intérêt
: dans les deux cas il y a du procédural. De plus pour mesurer l'intérêt de la
chose il faut comparer avec plus ou moins de volume :
1) 500 lignes
2) 5 000 lignes
3) 50 000 lignes
4) 500 000 lignes
5) 5 000 000 lignes
en faisant en sorte que le volume dépasse la RAM disponible pour voir quels sont
les effets du cache de données.

A +


"Patrice" a écrit dans le message de news:
eG1Pwy$%

Ce traitement peut-il être mis sous forme ensembliste (par exemple CASE) ?

Si on est *obligé* de parcourir séquentiellement les lignes d'une table,
le
curseur sera plus rapide qu'un parcours simulé à base de boucles et
d'instructions SQL...

Donc le cas d'école que tu as plus haut, tu peux te passer d'une boucle,
la
vraie comparaison serait donc plutôt avec un simple
UPDATE MaTable SET UneColonne=MonRésultat

Disons que pour être plus précis, la recommandation que voulait
transmettre
le formateur est de choisir toujours un traitement "ensembliste" par
rapport
à un parcours séquentiel explicite des données (et dans ce cas un CURSOR
peut être la meilleure solution).
--
Patrice

"MB" a écrit dans le message de
news:OzJYvU$%

Pour vous répondre, dans la boucle il y a gros traitement sur du contôle



de

données avec beaucoup if if if if ....

Pour le test, nous avons dans un premier temps supprimé tous les if if
if
if .... et comparé que les boucles sur le jeu de données avec et sans
curseur. C'est le curseur le plus rapide avec 1 minute de moins sur 8000
enregistrements.


"Patrice" a écrit dans le message de news:
%23dzFYb%23%

Tu veux dire sans doute bannir les "curseurs" et non pas les
"procédures
stockées" ?

Ta procédure stockée fait également un traitement procédural ce qui est
sans
doute le problème. Ce n'est pas à proprement parler les "curseurs" qui
sont
à "éviter" mais plutôt le traitement "procédural" par opposition aux
traitements ensemblistes...

Quel est ce fameux traitement ? N'est il pas réalisable avec une
instruction
SQL unique... Pour l'instant à part le flag et le comptage je ne vois





pas

trop ce que tu cherches à faire...

Après il y a des cas où tu es sans doute obligé...

--
Patrice

"MB" a écrit dans le message de
news:e8NlcD%23%

Bonjour
Je sort d'une formation et le discours était
Bannir les procèdures stokées
Bannir les select *

Nous n'avons pas encore poussé nos tests très loin mais pour l'instant
les
curseurs vont plus vite et les select * aussi !

voilà la méthode que l'on a utilisé
- voici un lien qui vous dira comment éviter les curseurs:
http://sqlpro.developpez.com/cours/sqlserver/MSSQLServer_avoidCursor/



et voilà note test

Avec curseur


DECLARE @nvc_PRE_IDE nvarchar(150)
DECLARE @nvc_NOM_IDE nvarchar(150)
DECLARE @nvc_PAT_NOM_JF nvarchar(150)
DECLARE @nvc_DEBUT_NOM nvarchar(10)
DECLARE @int_PAT_SEXE int
DECLARE @int_PAT_NAI_JJ int
DECLARE @int_PAT_NAI_MM int
DECLARE @int_PAT_NAI_AA int
DECLARE @int_IDE_CLE int


DECLARE @nvc_USG_CLE nvarchar(150)
DECLARE @cpt int







--- ---------------------------------------------------------------------





-

------------------------------------

--- On efface les anciens enregistrements de la base

DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
WHERE USG_CLE = @nvc_USG_CLE

SELECT
@cpt = count(*)
FROM TMP_TAB_REC_DOUBLONS_DS_BASE

IF @cpt = 0
BEGIN
TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE
END

SET @cpt = 0






--- ---------------------------------------------------------------------





-

------------------------------------



--- ---------------------------------------------------------------------





-

------------------------------------

--- Ouverture du curseur de parcours des enregistrements

DECLARE cur_CleIdentite CURSOR
FOR
SELECT
CLE_IDE
FROM ADR_TAB_IDENTITES
ORDER BY CLE_IDE

OPEN cur_CleIdentite

FETCH NEXT FROM cur_CleIdentite
INTO @int_IDE_CLE

WHILE @@FETCH_STATUS = 0
begin


--- ***************************************************
--- Corps du programme
SET @cpt = @cpt + 1
--- ********************************************************



FETCH NEXT FROM cur_CleIdentite
INTO @int_IDE_CLE
End

--- fermeture du curseur

Close cur_CleIdentite
DEALLOCATE cur_CleIdentite

print @cpt










____________________________________________________________________________

_______________


SANS CURSOR


DECLARE @nvc_PRE_IDE nvarchar(150)
DECLARE @nvc_PRE_IDE nvarchar(150);
DECLARE @nvc_NOM_IDE nvarchar(150);
DECLARE @nvc_PAT_NOM_JF nvarchar(150);
DECLARE @nvc_DEBUT_NOM nvarchar(10);
DECLARE @int_PAT_SEXE int;
DECLARE @int_PAT_NAI_JJ int;
DECLARE @int_PAT_NAI_MM int;
DECLARE @int_PAT_NAI_AA int;
DECLARE @int_IDE_CLE int;
DECLARE @cpt int;







--- ---------------------------------------------------------------------





-

------------------------------------

--- On efface les anciens enregistrements de la base

DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
WHERE USG_CLE = @nvc_USG_CLE;

SELECT
@cpt = count(*)
FROM TMP_TAB_REC_DOUBLONS_DS_BASE;


IF @cpt = 0
BEGIN
TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE;
END;


SET @cpt = 0;






--- ---------------------------------------------------------------------





-

------------------------------------



--- ---------------------------------------------------------------------





-

------------------------------------

--- On stocke les clé des identités dans une table temporaire

SELECT
CLE_IDE,
0 AS OK
INTO #TMP_CLE_IDE
FROM ADR_TAB_IDENTITES
ORDER BY CLE_IDE;

-- tant qu'il y a au moins une table à traiter
WHILE EXISTS(
SELECT
CLE_IDE
FROM #TMP_CLE_IDE
WHERE OK = 0)
BEGIN

-- prendre la clé de la première identité à traiter
SET @int_IDE_CLE = ( SELECT TOP 1 CLE_IDE
FROM #TMP_CLE_IDE WHERE OK = 0
ORDER BY 1);


---
********************************************************************
--- Corps du programme
SET @cpt = @cpt + 1

---
********************************************************************




-- flaguer l'objet traité dans la table des objets à traiter
UPDATE #TMP_CLE_IDE
SET OK = 1
WHERE CLE_IDE = @int_IDE_CLE;

--- Fin de la boucle WHILE
END;


-- supprimez la table temporaire de traitement
DROP TABLE #TMP_CLE_IDE;

print @cpt


voilou





















--
Frédéric BROUARD, MVP SQL Server, expert bases de données et langage SQL
Le site sur le langage SQL et les SGBDR : http://sqlpro.developpez.com
Audit, conseil, expertise, formation, modélisation, tuning, optimisation
********************* http://www.datasapiens.com ***********************
Avatar
MB
Merci
On va pousser un peu plus loin nos tests de performance

"Fred BROUARD" a écrit dans le message de news:
enoD$%23A$
bonjour,

MB a écrit:
Dans quel cas on est dans de la programmation *ensembliste*
Merci



1) lorsque TOUT le traitement est fait à l'aide d'une seule et unique
requête (UPDATE, INSERT, DELETE ou SELECT)

2) lorsqu'il y a une requête encapsulant des vues ou des expressions de
table (CTE)

3) lorsque le code n'a aucun branchement : notamment dans le cas de
requêtes SQL enchaînées pour des mises à jour combinées (par exemple table
fille + table mère).

Sinon, effectivement l'exemple choisit pour comparaison n'a pas de réel
intérêt : dans les deux cas il y a du procédural. De plus pour mesurer
l'intérêt de la chose il faut comparer avec plus ou moins de volume :
1) 500 lignes
2) 5 000 lignes
3) 50 000 lignes
4) 500 000 lignes
5) 5 000 000 lignes
en faisant en sorte que le volume dépasse la RAM disponible pour voir
quels sont les effets du cache de données.

A +


"Patrice" a écrit dans le message de news:
eG1Pwy$%

Ce traitement peut-il être mis sous forme ensembliste (par exemple CASE)
?

Si on est *obligé* de parcourir séquentiellement les lignes d'une table,
le
curseur sera plus rapide qu'un parcours simulé à base de boucles et
d'instructions SQL...

Donc le cas d'école que tu as plus haut, tu peux te passer d'une boucle,
la
vraie comparaison serait donc plutôt avec un simple
UPDATE MaTable SET UneColonne=MonRésultat

Disons que pour être plus précis, la recommandation que voulait
transmettre
le formateur est de choisir toujours un traitement "ensembliste" par
rapport
à un parcours séquentiel explicite des données (et dans ce cas un CURSOR
peut être la meilleure solution).
--
Patrice

"MB" a écrit dans le message de
news:OzJYvU$%

Pour vous répondre, dans la boucle il y a gros traitement sur du contôle



de

données avec beaucoup if if if if ....

Pour le test, nous avons dans un premier temps supprimé tous les if if
if
if .... et comparé que les boucles sur le jeu de données avec et sans
curseur. C'est le curseur le plus rapide avec 1 minute de moins sur 8000
enregistrements.


"Patrice" a écrit dans le message de news:
%23dzFYb%23%

Tu veux dire sans doute bannir les "curseurs" et non pas les
"procédures
stockées" ?

Ta procédure stockée fait également un traitement procédural ce qui est
sans
doute le problème. Ce n'est pas à proprement parler les "curseurs" qui
sont
à "éviter" mais plutôt le traitement "procédural" par opposition aux
traitements ensemblistes...

Quel est ce fameux traitement ? N'est il pas réalisable avec une
instruction
SQL unique... Pour l'instant à part le flag et le comptage je ne vois





pas

trop ce que tu cherches à faire...

Après il y a des cas où tu es sans doute obligé...

--
Patrice

"MB" a écrit dans le message de
news:e8NlcD%23%

Bonjour
Je sort d'une formation et le discours était
Bannir les procèdures stokées
Bannir les select *

Nous n'avons pas encore poussé nos tests très loin mais pour l'instant
les
curseurs vont plus vite et les select * aussi !

voilà la méthode que l'on a utilisé
- voici un lien qui vous dira comment éviter les curseurs:
http://sqlpro.developpez.com/cours/sqlserver/MSSQLServer_avoidCursor/



et voilà note test

Avec curseur


DECLARE @nvc_PRE_IDE nvarchar(150)
DECLARE @nvc_NOM_IDE nvarchar(150)
DECLARE @nvc_PAT_NOM_JF nvarchar(150)
DECLARE @nvc_DEBUT_NOM nvarchar(10)
DECLARE @int_PAT_SEXE int
DECLARE @int_PAT_NAI_JJ int
DECLARE @int_PAT_NAI_MM int
DECLARE @int_PAT_NAI_AA int
DECLARE @int_IDE_CLE int


DECLARE @nvc_USG_CLE nvarchar(150)
DECLARE @cpt int







--- ---------------------------------------------------------------------





-

------------------------------------

--- On efface les anciens enregistrements de la base

DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
WHERE USG_CLE = @nvc_USG_CLE

SELECT
@cpt = count(*)
FROM TMP_TAB_REC_DOUBLONS_DS_BASE

IF @cpt = 0
BEGIN
TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE
END

SET @cpt = 0






--- ---------------------------------------------------------------------





-

------------------------------------



--- ---------------------------------------------------------------------





-

------------------------------------

--- Ouverture du curseur de parcours des enregistrements

DECLARE cur_CleIdentite CURSOR
FOR
SELECT
CLE_IDE
FROM ADR_TAB_IDENTITES
ORDER BY CLE_IDE

OPEN cur_CleIdentite

FETCH NEXT FROM cur_CleIdentite
INTO @int_IDE_CLE

WHILE @@FETCH_STATUS = 0
begin


--- ***************************************************
--- Corps du programme
SET @cpt = @cpt + 1
--- ********************************************************



FETCH NEXT FROM cur_CleIdentite
INTO @int_IDE_CLE
End

--- fermeture du curseur

Close cur_CleIdentite
DEALLOCATE cur_CleIdentite

print @cpt










____________________________________________________________________________

_______________


SANS CURSOR


DECLARE @nvc_PRE_IDE nvarchar(150)
DECLARE @nvc_PRE_IDE nvarchar(150);
DECLARE @nvc_NOM_IDE nvarchar(150);
DECLARE @nvc_PAT_NOM_JF nvarchar(150);
DECLARE @nvc_DEBUT_NOM nvarchar(10);
DECLARE @int_PAT_SEXE int;
DECLARE @int_PAT_NAI_JJ int;
DECLARE @int_PAT_NAI_MM int;
DECLARE @int_PAT_NAI_AA int;
DECLARE @int_IDE_CLE int;
DECLARE @cpt int;







--- ---------------------------------------------------------------------





-

------------------------------------

--- On efface les anciens enregistrements de la base

DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
WHERE USG_CLE = @nvc_USG_CLE;

SELECT
@cpt = count(*)
FROM TMP_TAB_REC_DOUBLONS_DS_BASE;


IF @cpt = 0
BEGIN
TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE;
END;


SET @cpt = 0;






--- ---------------------------------------------------------------------





-

------------------------------------



--- ---------------------------------------------------------------------





-

------------------------------------

--- On stocke les clé des identités dans une table temporaire

SELECT
CLE_IDE,
0 AS OK
INTO #TMP_CLE_IDE
FROM ADR_TAB_IDENTITES
ORDER BY CLE_IDE;

-- tant qu'il y a au moins une table à traiter
WHILE EXISTS(
SELECT
CLE_IDE
FROM #TMP_CLE_IDE
WHERE OK = 0)
BEGIN

-- prendre la clé de la première identité à traiter
SET @int_IDE_CLE = ( SELECT TOP 1 CLE_IDE
FROM #TMP_CLE_IDE WHERE OK = 0
ORDER BY 1);


---
********************************************************************
--- Corps du programme
SET @cpt = @cpt + 1

---
********************************************************************




-- flaguer l'objet traité dans la table des objets à traiter
UPDATE #TMP_CLE_IDE
SET OK = 1
WHERE CLE_IDE = @int_IDE_CLE;

--- Fin de la boucle WHILE
END;


-- supprimez la table temporaire de traitement
DROP TABLE #TMP_CLE_IDE;

print @cpt


voilou





















--
Frédéric BROUARD, MVP SQL Server, expert bases de données et langage SQL
Le site sur le langage SQL et les SGBDR : http://sqlpro.developpez.com
Audit, conseil, expertise, formation, modélisation, tuning, optimisation
********************* http://www.datasapiens.com ***********************



Avatar
Fred BROUARD
pensez aussi à simuler l'activité réelle d'un serveur c'est à dire la
concurrence. En effet le gestion des verrous à une importance extrême dans les
performances de restitution et de mise à jour des données.
L'écriture dans un fichier plat sera toujours plus rapide que dans une base de
données. En revanche écrire concourrament dans le même fichier plat depuis
différents utilisateurs, à toutes les chances d'être sévèrement moins rapide que
dans le cas d'une écriture concurrente dans une base de données.

A +

MB a écrit:
Merci
On va pousser un peu plus loin nos tests de performance

"Fred BROUARD" a écrit dans le message de news:
enoD$%23A$

bonjour,

MB a écrit:

Dans quel cas on est dans de la programmation *ensembliste*
Merci



1) lorsque TOUT le traitement est fait à l'aide d'une seule et unique
requête (UPDATE, INSERT, DELETE ou SELECT)

2) lorsqu'il y a une requête encapsulant des vues ou des expressions de
table (CTE)

3) lorsque le code n'a aucun branchement : notamment dans le cas de
requêtes SQL enchaînées pour des mises à jour combinées (par exemple table
fille + table mère).

Sinon, effectivement l'exemple choisit pour comparaison n'a pas de réel
intérêt : dans les deux cas il y a du procédural. De plus pour mesurer
l'intérêt de la chose il faut comparer avec plus ou moins de volume :
1) 500 lignes
2) 5 000 lignes
3) 50 000 lignes
4) 500 000 lignes
5) 5 000 000 lignes
en faisant en sorte que le volume dépasse la RAM disponible pour voir
quels sont les effets du cache de données.

A +


"Patrice" a écrit dans le message de news:
eG1Pwy$%


Ce traitement peut-il être mis sous forme ensembliste (par exemple CASE)
?

Si on est *obligé* de parcourir séquentiellement les lignes d'une table,
le
curseur sera plus rapide qu'un parcours simulé à base de boucles et
d'instructions SQL...

Donc le cas d'école que tu as plus haut, tu peux te passer d'une boucle,
la
vraie comparaison serait donc plutôt avec un simple
UPDATE MaTable SET UneColonne=MonRésultat

Disons que pour être plus précis, la recommandation que voulait
transmettre
le formateur est de choisir toujours un traitement "ensembliste" par
rapport
à un parcours séquentiel explicite des données (et dans ce cas un CURSOR
peut être la meilleure solution).
--
Patrice

"MB" a écrit dans le message de
news:OzJYvU$%


Pour vous répondre, dans la boucle il y a gros traitement sur du contôle



de


données avec beaucoup if if if if ....

Pour le test, nous avons dans un premier temps supprimé tous les if if
if
if .... et comparé que les boucles sur le jeu de données avec et sans
curseur. C'est le curseur le plus rapide avec 1 minute de moins sur 8000
enregistrements.


"Patrice" a écrit dans le message de news:
%23dzFYb%23%


Tu veux dire sans doute bannir les "curseurs" et non pas les
"procédures
stockées" ?

Ta procédure stockée fait également un traitement procédural ce qui est
sans
doute le problème. Ce n'est pas à proprement parler les "curseurs" qui
sont
à "éviter" mais plutôt le traitement "procédural" par opposition aux
traitements ensemblistes...

Quel est ce fameux traitement ? N'est il pas réalisable avec une
instruction
SQL unique... Pour l'instant à part le flag et le comptage je ne vois





pas


trop ce que tu cherches à faire...

Après il y a des cas où tu es sans doute obligé...

--
Patrice

"MB" a écrit dans le message de
news:e8NlcD%23%


Bonjour
Je sort d'une formation et le discours était
Bannir les procèdures stokées
Bannir les select *

Nous n'avons pas encore poussé nos tests très loin mais pour l'instant
les
curseurs vont plus vite et les select * aussi !

voilà la méthode que l'on a utilisé
- voici un lien qui vous dira comment éviter les curseurs:
http://sqlpro.developpez.com/cours/sqlserver/MSSQLServer_avoidCursor/



et voilà note test

Avec curseur


DECLARE @nvc_PRE_IDE nvarchar(150)
DECLARE @nvc_NOM_IDE nvarchar(150)
DECLARE @nvc_PAT_NOM_JF nvarchar(150)
DECLARE @nvc_DEBUT_NOM nvarchar(10)
DECLARE @int_PAT_SEXE int
DECLARE @int_PAT_NAI_JJ int
DECLARE @int_PAT_NAI_MM int
DECLARE @int_PAT_NAI_AA int
DECLARE @int_IDE_CLE int


DECLARE @nvc_USG_CLE nvarchar(150)
DECLARE @cpt int







--- ---------------------------------------------------------------------





-


------------------------------------


--- On efface les anciens enregistrements de la base

DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
WHERE USG_CLE = @nvc_USG_CLE

SELECT
@cpt = count(*)
FROM TMP_TAB_REC_DOUBLONS_DS_BASE

IF @cpt = 0
BEGIN
TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE
END

SET @cpt = 0






--- ---------------------------------------------------------------------





-


------------------------------------



--- ---------------------------------------------------------------------





-


------------------------------------


--- Ouverture du curseur de parcours des enregistrements

DECLARE cur_CleIdentite CURSOR
FOR
SELECT
CLE_IDE
FROM ADR_TAB_IDENTITES
ORDER BY CLE_IDE

OPEN cur_CleIdentite

FETCH NEXT FROM cur_CleIdentite
INTO @int_IDE_CLE

WHILE @@FETCH_STATUS = 0
begin


--- ***************************************************
--- Corps du programme
SET @cpt = @cpt + 1
--- ********************************************************



FETCH NEXT FROM cur_CleIdentite
INTO @int_IDE_CLE
End

--- fermeture du curseur

Close cur_CleIdentite
DEALLOCATE cur_CleIdentite

print @cpt










____________________________________________________________________________


_______________


SANS CURSOR


DECLARE @nvc_PRE_IDE nvarchar(150)
DECLARE @nvc_PRE_IDE nvarchar(150);
DECLARE @nvc_NOM_IDE nvarchar(150);
DECLARE @nvc_PAT_NOM_JF nvarchar(150);
DECLARE @nvc_DEBUT_NOM nvarchar(10);
DECLARE @int_PAT_SEXE int;
DECLARE @int_PAT_NAI_JJ int;
DECLARE @int_PAT_NAI_MM int;
DECLARE @int_PAT_NAI_AA int;
DECLARE @int_IDE_CLE int;
DECLARE @cpt int;







--- ---------------------------------------------------------------------





-


------------------------------------


--- On efface les anciens enregistrements de la base

DELETE FROM TMP_TAB_REC_DOUBLONS_DS_BASE
WHERE USG_CLE = @nvc_USG_CLE;

SELECT
@cpt = count(*)
FROM TMP_TAB_REC_DOUBLONS_DS_BASE;


IF @cpt = 0
BEGIN
TRUNCATE TABLE TMP_TAB_REC_DOUBLONS_DS_BASE;
END;


SET @cpt = 0;






--- ---------------------------------------------------------------------





-


------------------------------------



--- ---------------------------------------------------------------------





-


------------------------------------


--- On stocke les clé des identités dans une table temporaire

SELECT
CLE_IDE,
0 AS OK
INTO #TMP_CLE_IDE
FROM ADR_TAB_IDENTITES
ORDER BY CLE_IDE;

-- tant qu'il y a au moins une table à traiter
WHILE EXISTS(
SELECT
CLE_IDE
FROM #TMP_CLE_IDE
WHERE OK = 0)
BEGIN

-- prendre la clé de la première identité à traiter
SET @int_IDE_CLE = ( SELECT TOP 1 CLE_IDE
FROM #TMP_CLE_IDE WHERE OK = 0
ORDER BY 1);


---
********************************************************************
--- Corps du programme
SET @cpt = @cpt + 1

---
********************************************************************




-- flaguer l'objet traité dans la table des objets à traiter
UPDATE #TMP_CLE_IDE
SET OK = 1
WHERE CLE_IDE = @int_IDE_CLE;

--- Fin de la boucle WHILE
END;


-- supprimez la table temporaire de traitement
DROP TABLE #TMP_CLE_IDE;

print @cpt


voilou

















--
Frédéric BROUARD, MVP SQL Server, expert bases de données et langage SQL
Le site sur le langage SQL et les SGBDR : http://sqlpro.developpez.com
Audit, conseil, expertise, formation, modélisation, tuning, optimisation
********************* http://www.datasapiens.com ***********************









--
Frédéric BROUARD, MVP SQL Server, expert bases de données et langage SQL
Le site sur le langage SQL et les SGBDR : http://sqlpro.developpez.com
Audit, conseil, expertise, formation, modélisation, tuning, optimisation
********************* http://www.datasapiens.com ***********************