Je travaille sur une base de données pour une petite application web dans mon école en utilisant SQL Server 2005
.
Je vois quelques écoles de pensée sur la question de varchar
vs nvarchar
:
- À utiliser
varchar
sauf si vous traitez un grand nombre de données internationalisées, puis utiliseznvarchar
. - Utilisez-le
nvarchar
pour tout.
Je commence à voir les mérites du point de vue 2. Je sais que nvarchar occupe deux fois plus d'espace, mais ce n'est pas nécessairement énorme car cela ne va stocker des données que pour quelques centaines d'étudiants. Pour moi, il semble qu'il serait plus facile de ne pas s'en inquiéter et de simplement autoriser tout le monde à utiliser nvarchar. Ou y a-t-il quelque chose qui me manque?
sql-server
sql-server-2005
storage
varchar
nvarchar
Jason Baker
la source
la source
NVARCHAR
", et cela peut avoir des impacts très négatifs sur les performances et les coûts / budgets matériels. Quelques rangées, voire quelques milliers, n'auront pas d'importance. Mais les systèmes se développent plus rapidement que prévu, de sorte que la réponse actuellement acceptée ne rend pas service à la communauté. Je vous remercie.Réponses:
Utilisez toujours nvarchar.
Vous n'aurez peut-être jamais besoin des caractères codés sur deux octets pour la plupart des applications. Cependant, si vous devez prendre en charge les langues à double octet et que vous ne disposez que d'une prise en charge à un seul octet dans votre schéma de base de données, il est très coûteux de revenir en arrière et de le modifier dans votre application.
Le coût de la migration d'une application de varchar vers nvarchar sera bien plus élevé que le peu d'espace disque supplémentaire que vous utiliserez dans la plupart des applications.
la source
L'espace disque n'est pas le problème ... mais la mémoire et les performances le seront. Double la lecture des pages, double taille de l'index, étrange LIKE et = comportement constant, etc.
Avez-vous besoin de stocker un script chinois, etc.? Oui ou non...
Et de MS BOL " Stockage et performances des effets d'Unicode "
Modifier :
Question SO récente soulignant à quel point les mauvaises performances de nvarchar peuvent être ...
SQL Server utilise un processeur élevé lors de la recherche dans les chaînes nvarchar
la source
Être cohérent! REJOINDRE un VARCHAR à NVARCHAR a un grand impact sur les performances.
la source
nvarchar
àvarchar
vs se convertirnvarchar
àvarchar
et se joindre àvarchar
. Sauf si vous vouliez bien sûr être cohérent dans les types de données des colonnes, pas dans la jonction.VARCHAR
etNVARCHAR
, cela devrait être dû à l'indexation de laVARCHAR
colonne ainsi qu'au type de classement utilisé pour cette colonne (et donc à l'index). Je couvre ce sujet en détail dans le billet de blog suivant: Impact sur les index lors du mélange des types VARCHAR et NVARCHAR .nvarchar va avoir une surcharge importante en mémoire, stockage, jeu de travail et indexation, donc si les spécifications dictent que ce ne sera jamais vraiment nécessaire, ne vous embêtez pas.
Je n'aurais pas de règle stricte et rapide "toujours nvarchar" car cela peut être un gaspillage complet dans de nombreuses situations - en particulier ETL de ASCII / EBCDIC ou des identificateurs et des colonnes de code qui sont souvent des clés et des clés étrangères.
D'un autre côté, il y a beaucoup de cas de colonnes, où je serais sûr de poser cette question tôt et si je n'obtenais pas une réponse rapide et rapide, je ferais la colonne nvarchar.
la source
J'hésite à ajouter une autre réponse ici car il y en a déjà pas mal, mais il faut faire quelques remarques qui n'ont pas été faites ou qui n'ont pas été faites clairement.
Premièrement: ne pas toujours utiliser
NVARCHAR
. C'est une attitude / approche très dangereuse et souvent coûteuse. Et il ne vaut pas mieux dire « N'utilisez jamais de curseurs» car ils sont parfois le moyen le plus efficace de résoudre un problème particulier, et la solution habituelle pour faire uneWHILE
boucle sera presque toujours plus lente qu'un curseur correctement fait.La seule fois où vous devriez utiliser le terme "toujours" est lorsque vous conseillez de "toujours faire ce qui est le mieux pour la situation". Certes, cela est souvent difficile à déterminer, en particulier lorsque vous essayez d'équilibrer les gains à court terme en temps de développement (gestionnaire: "nous avons besoin de cette fonctionnalité - que vous ne connaissiez pas jusqu'à présent - il y a une semaine!") Avec une longue - les coûts de maintenance à long terme (gestionnaire qui a initialement fait pression sur l'équipe pour terminer un projet de 3 mois dans un sprint de 3 semaines: "pourquoi avons-nous ces problèmes de performance? Comment aurions-nous pu faire X qui n'a pas de flexibilité? Nous ne pouvons pas nous permettre un sprint ou deux pour résoudre ce problème. Que pouvons-nous faire en une semaine pour revenir à nos éléments prioritaires? Et nous devons certainement consacrer plus de temps à la conception afin que cela ne se reproduise pas! ").
Deuxièmement: @ gbn répond à certains points très importants à prendre en compte lors de certaines décisions de modélisation de données lorsque le chemin n'est pas clair à 100%. Mais il y a encore plus à considérer:
Le gaspillage d'espace a un énorme effet de cascade sur l'ensemble du système. J'ai écrit un article expliquant en détail ce sujet: le disque est bon marché! ORLY? (inscription gratuite requise; désolé, je ne contrôle pas cette politique).
Troisièmement: bien que certaines réponses se concentrent incorrectement sur l'aspect "il s'agit d'une petite application" et que certaines suggèrent correctement "d'utiliser ce qui est approprié", aucune des réponses n'a fourni de véritables orientations au PO. Un détail important mentionné dans la question c'est que c'est une page web pour leur école. Génial! Nous pouvons donc suggérer que:
NVARCHAR
car, avec le temps, il est de plus en plus probable que des noms d'autres cultures apparaîtront à ces endroits.VARCHAR
avec la page de code appropriée (qui est déterminé à partir du classement du champ).INT
/TINYINT
puisque les codes ISO sont de longueur fixe, lisibles par l'homme et bien, standard :) utilisezCHAR(2)
pour les codes à deux lettres etCHAR(3)
si vous utilisez des codes à 3 lettres. Et pensez à utiliser un classement binaire tel queLatin1_General_100_BIN2
.VARCHAR
car il s'agit d'une norme internationale de ne jamais utiliser de lettre en dehors de AZ. Et oui, utilisez toujoursVARCHAR
même si vous ne stockez que des codes postaux américains et non INT, car les codes postaux ne sont pas des nombres, ce sont des chaînes et certains d'entre eux ont un "0" en tête. Et pensez à utiliser un classement binaire tel queLatin1_General_100_BIN2
.NVARCHAR
car les deux peuvent désormais contenir des caractères Unicode.Quatrièmement: Maintenant que les
NVARCHAR
données occupent deux fois plus d'espace que nécessaire pour les données qui s'intègrent bienVARCHAR
("s'intègre bien" = ne se transforme pas en "?") Et, d'une manière ou d'une autre, comme par magie, l'application s'est développée et maintenant il y a des millions d'enregistrements dans au moins un de ces champs où la plupart des lignes sont en ASCII standard mais certaines contiennent des caractères Unicode, vous devez donc les conserverNVARCHAR
, tenez compte des points suivants:Si vous utilisez SQL Server 2008-2016 RTM et que vous êtes sur Enterprise Edition, OU si vous utilisez SQL Server 2016 SP1 (qui a rendu la compression de données disponible dans toutes les éditions) ou une version plus récente, vous pouvez activer la compression de données . La compression des données peut (mais pas "toujours") compresser les données Unicode dans les champs
NCHAR
etNVARCHAR
. Les facteurs déterminants sont:NCHAR(1 - 4000)
etNVARCHAR(1 - 4000)
utiliser le schéma de compression standard pour Unicode , mais uniquement à partir de SQL Server 2008 R2, ET uniquement pour les données IN ROW, pas OVERFLOW! Cela semble être meilleur que l'algorithme de compression ROW / PAGE habituel.NVARCHAR(MAX)
etXML
(et je suppose aussiVARBINARY(MAX)
,TEXT
etNTEXT
) les données IN ROW (pas hors ligne dans les pages LOB ou OVERFLOW) peuvent au moins être compressées en PAGE, mais pas en ROW. Bien sûr, la compression de PAGE dépend de la taille de la valeur en ligne: j'ai testé avec VARCHAR (MAX) et j'ai vu que 6000 lignes de caractères / octets ne se comprimeraient pas, mais 4000 lignes de caractères / octets le faisaient.Si vous utilisez SQL Server 2005 ou 2008-2016 RTM et non sur Enterprise Edition, vous pouvez avoir deux champs: un
VARCHAR
et unNVARCHAR
. Par exemple, supposons que vous stockiez des URL qui sont pour la plupart toutes des caractères ASCII de base (valeurs 0 - 127) et qui, par conséquent, tiennent dansVARCHAR
, mais ont parfois des caractères Unicode. Votre schéma peut inclure les 3 champs suivants:Dans ce modèle, vous ne sélectionnez que dans la
[URL]
colonne calculée. Pour l'insertion et la mise à jour, vous déterminez le champ à utiliser en voyant si la conversion modifie la valeur entrante, qui doit être deNVARCHAR
type:Vous pouvez GZIP les valeurs entrantes
VARBINARY(MAX)
puis décompressez à la sortie:COMPRESS
etDECOMPRESS
, qui sont également GZip.Si vous utilisez SQL Server 2017 ou une version plus récente, vous pouvez envisager de faire de la table un index de colonnes en cluster.
Bien que ce n'est pas une option viable encore, SQL Server 2019 introduit un support natif pour UTF-8 dans
VARCHAR
/CHAR
types de données. Il y a actuellement trop de bogues avec lui pour qu'il soit utilisé, mais s'ils sont corrigés, alors c'est une option pour certains scénarios. Veuillez consulter mon article, " Prise en charge native UTF-8 dans SQL Server 2019: Sauveur ou faux prophète? ", Pour une analyse détaillée de cette nouvelle fonctionnalité.la source
Pour votre application, nvarchar est très bien car la taille de la base de données est petite. Dire «toujours utiliser nvarchar» est une vaste simplification excessive. Si vous n'êtes pas obligé de stocker des choses comme Kanji ou d'autres personnages fous, utilisez VARCHAR, cela utilisera beaucoup moins d'espace. Mon prédécesseur dans mon travail actuel a conçu quelque chose en utilisant NVARCHAR quand il n'était pas nécessaire. Nous l'avons récemment remplacé par VARCHAR et avons économisé 15 Go sur cette table (il était très écrit). De plus, si vous avez alors un index sur cette table et que vous souhaitez inclure cette colonne ou créer un index composite, vous venez d'agrandir la taille de votre fichier d'index.
Soyez juste réfléchi dans votre décision; dans le développement SQL et les définitions de données, il semble rarement y avoir une "réponse par défaut" (à part éviter les curseurs à tout prix, bien sûr).
la source
Étant donné que votre application est petite, il n'y a essentiellement aucune augmentation de coût appréciable pour l'utilisation de nvarchar sur varchar, et vous vous épargnez des maux de tête potentiels si vous avez besoin de stocker des données Unicode.
la source
En général; Commencez avec le type de données le plus cher qui a le moins de contraintes. Mettez-le en production . Si les performances commencent à être un problème, découvrez ce qui est réellement stocké dans ces
nvarchar
colonnes. Y a-t-il des personnages qui ne rentreraient pasvarchar
? Sinon, passez à varchar. N'essayez pas de pré-optimiser avant de savoir où se trouve la douleur. Je suppose que le choix entre nvarchar / varchar n'est pas ce qui va ralentir votre application dans un avenir prévisible. Il y aura d'autres parties de l'application où le réglage des performances vous donnera beaucoup plus pour les dollars .la source
Depuis quelques années, tous nos projets utilisent NVARCHAR pour tout, car tous ces projets sont multilingues. Les données importées de sources externes (par exemple un fichier ASCII, etc.) sont converties en Unicode avant d'être insérées dans la base de données.
Je n'ai pas encore rencontré de problèmes liés aux performances des index plus grands, etc. Les index utilisent plus de mémoire, mais la mémoire est bon marché.
Que vous utilisiez des procédures stockées ou que vous construisiez du SQL à la volée, assurez-vous que toutes les constantes de chaîne sont préfixées par N (par exemple SET @foo = N'Hello world. ';) Afin que la constante soit également Unicode. Cela évite toute conversion de type de chaîne lors de l'exécution.
YMMV.
la source
Je peux parler d'expérience à ce sujet, méfiez-vous
nvarchar
. Sauf si vous en avez absolument besoin, ce type de champ de données détruit les performances sur une plus grande base de données. J'ai hérité d'une base de données qui souffrait en termes de performances et d'espace. Nous avons pu réduire de 70% la taille d'une base de données de 30 Go! Il y a eu quelques autres modifications pour améliorer les performances, mais je suis sûr que celavarchar
a également beaucoup aidé. Si votre base de données a le potentiel de développer des tables à plus d'un million d'enregistrements, restez à l'écartnvarchar
à tout prix.la source
Je traite souvent cette question au travail:
Flux FTP d'inventaire et de prix - Les descriptions d'articles et autres textes étaient dans nvarchar lorsque varchar fonctionnait bien. La conversion de ces derniers en varchar a réduit la taille du fichier presque de moitié et a vraiment aidé avec les téléchargements.
Le scénario ci-dessus a bien fonctionné jusqu'à ce que quelqu'un mette un caractère spécial dans la description de l'article (peut-être une marque de commerce, je ne me souviens pas)
Je n'utilise toujours pas nvarchar à chaque fois via varchar. En cas de doute ou de potentiel pour les caractères spéciaux, j'utilise nvarchar. Je trouve que j'utilise varchar surtout lorsque je contrôle à 100% ce qui remplit le champ.
la source
Pourquoi, dans toute cette discussion, n'a-t-il pas été fait mention de l'UTF-8? Être capable de stocker la plage de caractères unicode complète ne signifie pas qu'il faut toujours allouer deux octets par caractère (ou "point de code" pour utiliser le terme UNICODE). Tout ASCII est UTF-8. SQL Server vérifie-t-il pour les champs VARCHAR () que le texte est strict ASCII (c'est-à-dire le bit zéro du premier octet)? J'espère que non.
Si vous souhaitez ensuite stocker unicode et que vous souhaitez la compatibilité avec les anciennes applications ASCII uniquement, je pense que l'utilisation de VARCHAR () et UTF-8 serait la solution miracle: il n'utilise plus d'espace que nécessaire.
Pour ceux d'entre vous qui ne connaissent pas l'UTF-8, puis-je recommander un apprêt .
la source
N
types XML et préfixés). Vous n'avez pas le choix d'utiliser UTF-8. De plus, les codages Unicode (UTF-8, UCS-2 / UTF-16 et UTF-32) ne peuvent pas être appliqués aux champs VARCHAR.Il y aura des cas exceptionnels où vous voudrez restreindre délibérément le type de données pour vous assurer qu'il ne contient pas de caractères d'un certain ensemble. Par exemple, j'avais un scénario où j'avais besoin de stocker le nom de domaine dans une base de données. L'internationalisation des noms de domaine n'était pas fiable à l'époque, il était donc préférable de limiter l'entrée au niveau de la base et d'éviter tout problème potentiel.
la source
Si vous utilisez
NVARCHAR
simplement parce qu'une procédure stockée système l'exige, l'occurrence la plus fréquente étant inexplicablesp_executesql
et que votre SQL dynamique est très long, vous feriez mieux de faire des manipulations de chaînes (concaténation, remplacement, etc.) du point de vue des performances,VARCHAR
puis de convertir le résultat finalNVARCHAR
et l'introduire dans le paramètre proc. Alors non, ne l'utilisez pas toujoursNVARCHAR
!la source