Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

SQL Server : Différence de calcul du CHECKSUM sur SQL Server 2005 et 2008 ou sur les plateformes 32 bits et 64 bits ?

Ayant eu vent d'une différence de comportement entre version (2005 et 2008) ou entre plateforme de SQL Server (32 bits et 64 bits) de la fonction CHECKSUM, je me suis dit qu'il fallait creuser un peu.

En effet il n'est pas impossible qu'il y ai une telle différence, mais généralement, soit elle est annoncée à l'avance, soit c'est purement et simplement un bug. Il y a déjà des précèdent par exemple le calcul des Hash entre la plateforme x64 et x86 :

string s = "azerty" ;

Console.WriteLine(s.GetHashCode().ToString());

Donne en 32 bits:

765360530

Et en 64 bits:

1423019289

Sur SQL Server, l'équipe de développement essaye de conserver un comportement similaire quelques soit la plateforme, même s'il peut arriver qu'une fonction renvoie des valeurs légèrement différente d'une version ou plateforme à l'autre. Mais ces comportement sont souvent passés à la loupe, car imaginez un Hash Index (http://blogs.codes-sources.com/christian/archive/2009/09/22/sql-server-hash-index-ou-comment-indexer-de-tr-s-grosses-colonnes.aspx) qui se retrouverait avec des valeurs différentes suite à une montée de version ou un changement de serveur lors d'un basculement, il y aurait de quoi s'affoler !

Le calcul du CHECKSUM sur SQL Server se fera par :

SELECT CHECKSUM('azerty')

Le résultat obtenu est clairement différent de celui .Net, ce qui confirme un algorithme différent.

139376054

A noter une particularité lié au type de données dans le calcul de la fonction précédente. En effet, si je mets ma chaîne en type Unicode (N majuscule précédent celle-ci):

SELECT CHECKSUM(N'azerty')

On obtient alors un résultat différent :

-1258351920

Passons aux tests sur des versions / plateforme différentes, avec la requête suivant, renvoyant le CHECKSUM, la version et la plateforme (simplifié, je n'ai pas inlus le IA64... je n'ai pas de tels serveurs) :

select CHECKSUM('azerty'), SERVERPROPERTY('ProductVersion'), CASE WHEN PATINDEX('%X86%', @@VERSION) != 0 THEN '32 bits' ELSE '64 bits' END

La requête précédente est exécutée sur un ensemble de serveurs équipés de versions et plateformes hétérogènes pour se faire une idée du résultat.

Voici les resulats :

CHECKSUM

VERSION

Plateforme

139376054

10.0.2734.0

64 bits

139376054

10.0.2746.0

64 bits

139376054

9.00.4266.00

64 bits

139376054

10.0.2746.0

64 bits

139376054

10.0.2734.0

64 bits

139376054

10.0.2734.0

64 bits

139376054

10.0.2734.0

64 bits

139376054

10.0.2734.0

64 bits

139376054

10.0.2746.0

64 bits

139376054

10.0.2734.0

64 bits

-1258351920

9.00.4220.00

32 bits

139376054

10.0.2734.0

64 bits

139376054

10.0.2746.0

64 bits

139376054

10.0.2746.0

64 bits

139376054

10.0.2734.0

64 bits

139376054

10.0.2746.0

64 bits

139376054        

9.00.4207.00

32 bits

Seule une ligne est différente des autres. On pourrait conclure à une différence de comportement de SQL Server 2005 en 32 bits, mais non. Une autre ligne montre cette même combinaison de version et plateforme avec un résultat identique.

D'où vient alors la différence ? Si vous avez suivi mes 2 exemples en SQL, vous avez vu que le CHECKSUM diffère quand le type de la chaîne change… Or il y a un paramètre qui a une grosse incidence sur çà : Le classement (COLLATE).

Si on ajoute à la liste de notre SELECT :

SERVERPROPERTY('Collation')

On obtient la liste (j'ai ajouté 2 serveurs en plus par rapport à la requête précédente, pour confirmer le comportement,):

CHECKSUM

Version

Plateforme

Classement Serveur

139376054

10.0.2734.0

64 bits

SQL_Latin1_General_CP1_CI_AS

139376054

9.00.4266.00

64 bits

SQL_Latin1_General_CP1_CI_AS

139376054

10.0.2746.0

64 bits

SQL_Latin1_General_CP1_CI_AS

139376054

10.0.2746.0

64 bits

SQL_Latin1_General_CP1_CI_AS

139376054

10.0.2734.0

64 bits

SQL_Latin1_General_CP1_CI_AS

139376054

10.0.2734.0

64 bits

SQL_Latin1_General_CP1_CI_AS

139376054

10.0.2746.0

64 bits

SQL_Latin1_General_CP1_CI_AS

-1258351920

9.00.4220.00

32 bits

Latin1_General_CI_AS

139376054

10.0.2734.0

64 bits

SQL_Latin1_General_CP1_CI_AS

139376054

10.0.2746.0

64 bits

SQL_Latin1_General_CP1_CI_AS

139376054

10.0.2734.0

64 bits

SQL_Latin1_General_CP1_CI_AS

139376054

10.0.2734.0

64 bits

SQL_Latin1_General_CP1_CI_AS

139376054

10.0.2734.0

64 bits

SQL_Latin1_General_CP1_CI_AS

139376054

10.0.2746.0

64 bits

SQL_Latin1_General_CP1_CI_AS

139376054

10.0.2746.0

64 bits

SQL_Latin1_General_CP1_CI_AS

139376054

10.0.2734.0

64 bits

SQL_Latin1_General_CP1_CI_AS

139376054

9.00.4207.00

32 bits

SQL_Latin1_General_CP1_CI_AS

-1258351920

10.0.2734.0

64 bits

Latin1_General_100_CI_AS

139376054

10.25.9084.0

(SQL Azure)

64 bits

SQL_Latin1_General_CP1_CI_AS

-1258351920

10.0.2531.0

64 bits

French_CI_AS

-1258351920

10.50.1352.12

(SQL Server 2008 R2 CTP Nov.)

64 bits

Latin1_General_100_CI_AS

Cette fois ci la différence est flagrante, ce n'est pas de la plateforme ou de la version de SQL Server que dépend le calcul de CHECKSUM, mais du classement courant ! Plus précisément de la différence entre les classements Windows (Latin1_General, Latin1_General_100 et …) et les classements SQL (SQL_Latin1_General_CP1). Le comportement du classement Windows est d'implicitement convertir les constantes de chaîne de caractères en chaîne Unicode.

Pour confirmer ce comportement, et accessoirement déterminer si c'est le classement du serveur ou celui de la base de données qui est pris en compte (et là on croise les doigts pour que ce soit le second, sinon gare aux problèmes dans ses bases de données), on va essayer un autre script :

CREATE DATABASE x COLLATE Latin1_General_CI_AS
GO

CREATE DATABASE y COLLATE SQL_Latin1_General_CP1_CI_AS
GO

USE x
GO

SELECT CHECKSUM('azerty')
GO

USE y
GO

SELECT CHECKSUM('azerty')
GO

Je vous laisse découvrir le résultat par vous-même. Disons que c'est celui que l'on pouvait espérer dans le meilleur des cas : c'est le classement de la base de données courante qui est pris en considération.

Faites donc très attention à la base de données courante lors des calculs de CHECKSUM. Cependant, la plateforme et la version ne sont pas en cause dans ces formes de calculs... Heureusement j'aurais auguré le pire pour certaines migrations et même backup/restore de certaines applications si tel n'avait pas été le cas.

Bonne somme de contrôle…

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Publié mercredi 16 décembre 2009 15:39 par christian
Classé sous : ,

Commentaires

Pas de commentaires
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- [MIX10] Release Candidate de Silverlight 4 et RIA Services par Blog Technique d'Audrey PETIT le il y a 27 minutes

- Premieres impressions sur Windows Phone 7 par Perspective le il y a 35 minutes

- [WindowsPhone7] Lecteur de flux RSS par Vko le il y a 8 heures et 59 minutes

- [WP7] L’émulateur Windows Phone 7 est multitâche par Kévin Gosse le il y a 9 heures et 52 minutes

- Présentation Club MOSS ce jour “La nouvelle architecture de Services SharePoint 2010”… par Le blog de Patrick le il y a 11 heures et 17 minutes

- [WindowPhone7] Premiers pas par Vko le il y a 11 heures et 38 minutes

- [WP7] Le SDK de Windows Phone 7 est disponible ! par Kévin Gosse le il y a 12 heures et 30 minutes

- SQL Server : PHP et SQL Server par SQL Server vu par Christian Robert le il y a 19 heures et 54 minutes

- [TechDays 2010] Windows Azure AppFabric (CLO305) par NeuroCypher's Blog le il y a 21 heures et 5 minutes

- Outils d’import avec mise à jour dans Microsoft Dynamics CRM par Bianca le il y a 21 heures et 13 minutes