y a-t-il un avantage à varchar (500) par rapport à varchar (8000)?


90

J'ai lu à ce sujet sur les forums MSDN et ici et je ne suis toujours pas clair. Je pense que c'est correct: Varchar (max) sera stocké en tant que type de données texte, ce qui présente des inconvénients. Disons donc que votre champ sera sûrement inférieur à 8000 caractères. Comme un champ BusinessName dans ma table de base de données. En réalité, un nom d'entreprise sera probablement toujours sous (tirant un numéro de mon chapeau) 500 caractères. Il semble que beaucoup de champs varchar que je rencontre tombent bien sous le nombre de caractères 8k.

Dois-je donc faire de ce champ un varchar (500) au lieu de varchar (8000)? D'après ce que je comprends de SQL, il n'y a aucune différence entre les deux. Donc, pour vous faciliter la vie, je voudrais définir tous mes champs varchar comme varchar (8000). Cela a-t-il des inconvénients?

Connexes: Taille des colonnes varchar (je n'avais pas l'impression que celle-ci répondait à ma question).


6
Imaginez essayer de faire figurer un nom d'entreprise de 500 caractères sur une carte de visite ... :)
OMG Ponies

2
@OMG Ponies: chaque fois que je vois votre nom d'utilisateur, je rigole. Maintenant, que disiez-vous? (Je plaisante)
jcollum

4
@jcollum: SpaceMan Spiff obtiendra toujours mon vote. Ce n'est pas vrai - n'importe quel Calvin & Hobbes fera l'affaire, mais surtout ceux qui sculptent la neige. Ou le tyranosaurus pilotant un F-14. Mais je m'égare ...
OMG Ponies

Réponses:


20

Du point de vue du traitement, cela ne fera aucune différence d'utiliser varchar (8000) vs varchar (500). C'est plus une sorte de "bonne pratique" de définir une longueur maximale qu'un champ doit contenir et de rendre votre varchar cette longueur. C'est quelque chose qui peut être utilisé pour aider à la validation des données. Par exemple, une abréviation d'état doit être de 2 caractères ou un code postal / zip de 5 ou 9 caractères. C'était une distinction plus importante lorsque vos données interagissaient avec d'autres systèmes ou interfaces utilisateur où la longueur du champ était critique (par exemple un jeu de données de fichier plat mainframe), mais de nos jours, je pense que c'est plus une habitude qu'autre chose.


3
Cela a du sens ... pour des choses qui ont naturellement une longueur maximale. Mais que faites-vous lorsque la longueur maximale n'est pas évidente? Par exemple, un nom commercial.
jcollum

2
Pour quelque chose comme ça, si je ne prévois aucun moyen de prévoir ce que la taille pourrait être, alors j'irai généralement avec un varchar (8000) ou varchar (max), selon le type de données
BBlake

4
Il semble que cela fasse une différence dans les performances, même en 2017: dba.stackexchange.com/a/162117/1822
a_horse_with_no_name

1
Des réponses plus récentes montrent qu'il ya des coûts: elle affecte la logique d'optimisation de la réponse de Martin Smith et aussi envisager 8K questions de taille total des lignes mentionnées par GBN et Oliver .
ToolmakerSteve

124

Un exemple où cela peut faire une différence est que cela peut empêcher une optimisation des performances qui évite d'ajouter des informations de version de ligne aux tables avec des déclencheurs after.

Ceci est couvert par SQL Kiwi ici

La taille réelle des données stockées n'a pas d'importance - c'est la taille potentielle qui compte.

De même, si vous utilisez des tables à mémoire optimisée depuis 2016, il est possible d'utiliser des colonnes LOB ou des combinaisons de largeurs de colonne qui pourraient potentiellement dépasser la limite d'entrée, mais avec une pénalité.

(Max) les colonnes sont toujours stockées hors ligne. Pour les autres colonnes, si la taille de ligne de données dans la définition de table peut dépasser 8 060 octets, SQL Server déplace la ou les plus grandes colonnes de longueur variable hors ligne. Encore une fois, cela ne dépend pas de la quantité de données que vous y stockez.

Cela peut avoir un effet négatif important sur la consommation de mémoire et les performances

Un autre cas où la surdéclaration des largeurs de colonne peut faire une grande différence est si la table sera un jour traitée à l'aide de SSIS. La mémoire allouée pour les colonnes de longueur variable (non BLOB) est fixe pour chaque ligne dans un arbre d'exécution et correspond à la longueur maximale déclarée des colonnes, ce qui peut conduire à une utilisation inefficace des tampons mémoire (exemple) . Bien que le développeur du package SSIS puisse déclarer une taille de colonne plus petite que la source, cette analyse est mieux effectuée à l'avance et appliquée à cet endroit.

De retour dans le moteur SQL Server lui-même, un cas similaire est celui lors du calcul de l'allocation de mémoire à allouer pour les SORTopérations, SQL Server suppose que les varchar(x)colonnes consommeront en moyenne des x/2octets.

Si la plupart de vos varcharcolonnes sont plus pleines que cela, cela peut entraîner des sortdébordements d'opérations tempdb.

Dans votre cas, si vos varcharcolonnes sont déclarées sous forme d' 8000octets mais ont en fait un contenu beaucoup moins important que cela, votre requête se verra allouer de la mémoire dont elle n'a pas besoin, ce qui est évidemment inefficace et peut conduire à des attentes d'attribution de mémoire.

Ceci est couvert dans la partie 2 du Webcast 1 des ateliers SQL téléchargeable à partir d'ici ou voir ci-dessous.

use tempdb;

CREATE TABLE T(
id INT IDENTITY(1,1) PRIMARY KEY,
number int,
name8000 VARCHAR(8000),
name500 VARCHAR(500))

INSERT INTO  T 
(number,name8000,name500)
SELECT number, name, name /*<--Same contents in both cols*/
FROM master..spt_values

SELECT id,name500
FROM T
ORDER BY number

Capture d'écran

SELECT id,name8000
FROM T
ORDER BY number

Capture d'écran


1
donc, si presque toutes mes valeurs sont 3 ou 4 caractères, ne peuvent jamais dépasser 4 caractères et que je veux éviter les "opérations de tri débordant sur tempdb", je déclarerai ma colonne VARCHAR (8) et utiliserai une contrainte CHECK pour appliquer cette colonne la largeur ne peut pas dépasser 4 caractères. Qu'est-ce que tu penses?
AK

12
@AlexKuznetsov - Pour cette situation, je les déclarerais char(4)car il y a de toute façon 2 octets de surcharge par colonne variable.
Martin Smith

9

En dehors des meilleures pratiques (réponse de BBlake)

  • Vous obtenez des avertissements sur la taille de ligne maximale (8060) octets et la largeur d'index (900 octets) avec DDL
  • DML mourra si vous dépassez ces limites
  • ANSI PADDING ON est la valeur par défaut, vous pourriez donc finir par stocker une charge complète d'espaces blancs

38
Juste pour clarifier à propos de ANSI PADDING ON: lors de l'utilisation de nvarcharet varchartypes, cela signifie uniquement que les espaces de fin sont préservés lors de l'insertion - pas que les valeurs sont remplies d'espaces à la taille de la colonne, comme dans charet nchar.
Ben M

9

Les grandes colonnes présentent certains inconvénients qui sont un peu moins évidents et qui pourraient vous surprendre un peu plus tard:

  • Toutes les colonnes que vous utilisez dans un INDEX - ne doivent pas dépasser 900 octets
  • Toutes les colonnes d'une clause ORDER BY ne doivent pas dépasser 8060 octets. C'est un peu difficile à comprendre car cela ne s'applique qu'à certaines colonnes. Voir Dépassement de la taille de ligne de SQL 2008 R2 pour plus de détails)
  • Si la taille totale de la ligne dépasse 8060 octets, vous obtenez une " page spill " pour cette ligne. Cela peut affecter les performances (une page est une unité d'allocation dans SQLServer et est fixée à 8000 octets + une surcharge. Le dépassement ne sera pas grave, mais c'est perceptible et vous devriez essayer de l'éviter si vous le pouvez facilement)
  • De nombreuses autres structures de données internes, tampons et enfin, vos propres variables et variables de table doivent tous refléter ces tailles. Avec des tailles excessives, une allocation de mémoire excessive peut affecter les performances

En règle générale, essayez d'être prudent avec la largeur de la colonne. Si cela devient un problème, vous pouvez facilement l'élargir pour répondre aux besoins. Si vous remarquez des problèmes de mémoire plus tard, réduire une colonne large plus tard peut devenir impossible sans perdre de données et vous ne saurez pas par où commencer.

Dans votre exemple de noms d'entreprise, réfléchissez à l'endroit où vous pouvez les afficher. Y a-t-il vraiment de la place pour 500 caractères ?? Sinon, il est inutile de les stocker en tant que tels. http://en.wikipedia.org/wiki/List_of_companies_of_the_United_States répertorie certains noms de sociétés et le maximum est d'environ 50 caractères. J'utiliserais donc 100 pour la colonne max. Peut-être plus comme 80.


2

Idéalement, vous voudriez être plus petit que cela, jusqu'à une longueur de taille raisonnable (500 n'est pas de taille raisonnable) et vous assurer que la validation du client détecte lorsque les données vont être trop volumineuses et envoyer une erreur utile.

Alors que le varchar ne va pas réellement réserver d'espace dans la base de données pour l'espace inutilisé, je me souviens que les versions de SQL Server avaient un snit sur les lignes de base de données étant plus larges qu'un certain nombre d'octets (ne me souviens pas du nombre exact) et jetant en fait toutes les données ne correspondaient pas. Un certain nombre de ces octets étaient réservés à des éléments internes à SQL Server.


vrai, c'était aussi une préoccupation beaucoup plus grande. Mais de nos jours, l'espace est vraiment bon marché, donc je ne pense pas que ce soit un si gros problème à considérer, du moins de mon point de vue.
BBlake

1
@jcollum: Dans votre exemple, 500 ne semble pas de taille raisonnable pour un nom d'entreprise.
Otis le

1
@BBlake: Quel que soit le coût du stockage, si SQL Server a toujours des contraintes de taille de ligne, peu importe la quantité de stockage dont vous disposez. Vous pouvez tout stocker dans des textblobs, mais certaines opérations SQL ne peuvent pas être effectuées sur un blob que vous pouvez effectuer sur un varchar.
Otis le

2
@Otis: mon point est le suivant: il n'y a aucune contrainte réelle sur la taille d'un nom d'entreprise. Sauf s'il y a une loi quelque part. Donc, dans ce cas, je ferais ce champ varchar (8000) et je l'appellerais un jour. Ma pensée va comme ceci: une vraie contrainte? varchar (x). Pas de vraie contrainte? varchar (8000).
jcollum

24
Je pensais qu'une trentaine de caractères était bon pour les noms de villes, jusqu'à ce que je voie El Pueblo de Nuestra Señora la Reina de los Ángeles del Río de Porciúncula
StuartLC
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.