Utilizzando il testo MAX o un tipo più specifico, più piccolo


22

Qualcuno stava rivedendo il mio codice DDL per la creazione di tabelle e mi ha suggerito, quando hanno visto che ho visto l'uso dei VARCHAR(256)campi per il testo, mi aspetto che sia piuttosto piccolo, come un nome o altro, che dovrei sempre usare VARCHAR(MAX)e collegare Perché usare qualsiasi cosa tranne varchar (max ) . L'ho letto ma sembrava datato, dato che si stava concentrando sul 2005, e non sembrava offrire alcuna vera giustificazione per allocare potenzialmente fino a 2 GB per riga su tutti i campi di testo.

Dal punto di vista delle prestazioni, dell'archiviazione, ecc., Come si può decidere se utilizzare VARCHAR(MAX)o un tipo più piccolo e specifico per le versioni moderne di SQL Server? (ad es. 2008, 2012, 2014)

Risposte:


31

Devo usare sempre (n)varchar(max)per le colonne di testo?

No.

Per SQL Server, i maxtipi di dati devono essere specificati solo in assenza di alternative. Si dovrebbe invece scegliere il tipo di base corretto ( varcharo nvarchar) e specificare una lunghezza massima esplicita adeguata ai dati da archiviare.

L'archiviazione fisica è identica se la colonna è digitata come varchar(n)o varchar(max), quindi non è questo il problema.

I motivi per non scegliere (n)varchar(max)ovunque ruotano attorno a funzionalità, qualità del piano e prestazioni.

Un elenco esaustivo non è probabilmente pratico, ma tra le altre maxcolonne:

Caratteristiche

  • Richiede un vincolo separato per imporre una lunghezza massima
  • Non può essere una chiave in un indice (quindi nessun vincolo univoco)
  • Può impedire il DDL online (comprese le ricostruzioni dell'indice e l'aggiunta di una nuova colonna non nulla)
  • In genere non sono supportate funzionalità "più recenti", ad esempio columnstore
  • Consultare la documentazione del prodotto per funzionalità e limitazioni più specifiche. Lo schema generale è che ci sono limiti e restrizioni imbarazzanti attorno maxai tipi di dati. Non tutte le limitazioni e gli effetti collaterali sono documentati.

Prestazione

  • Richiede una gestione speciale nel motore di esecuzione, per tenere conto delle dimensioni potenzialmente molto grandi. In genere, ciò implica l'utilizzo di un percorso di codice meno efficiente, con un'interfaccia di streaming
  • Potrebbe avere conseguenze impreviste simili per il codice esterno (e altri componenti di SQL Server come SSIS), che deve anche essere preparato per gestire dati con dimensioni fino a 2 GB
  • Si presume che siano larghi 4000 byte nei calcoli della concessione di memoria. Ciò può portare a un'eccessiva prenotazione di memoria, che limita la concorrenza e spinge fuori dalla memoria cache preziose pagine di indice e dati
  • Disabilita diverse importanti ottimizzazioni delle prestazioni
  • Può prolungare la durata del blocco
  • Può impedire all'ottimizzatore di scegliere un piano di ricerca (non dinamico)
  • Impedire che i filtri vengano inseriti nelle scansioni e vengano cercati come residui
  • Può aumentare la pressione e la contesa del tempdb (in base alla versione), poiché è probabile che anche variabili e parametri vengano digitati in modo maxda corrispondere alle definizioni delle colonne

In sintesi, ci sono così tanti effetti collaterali sottili (e indesiderabili) dell'uso inutile dello maxspecificatore che non ha senso farlo. La 'convenienza' minore di usare una singola dichiarazione non è una sorta di compensazione.

Valuta ogni tipo nel contesto, usa il tipo di base corretto ( varcharo nvarchar) e una lunghezza esplicita ragionevole.

Ulteriori letture:


8

Leggerà come la risposta di un paranoico, ma non ci sono solo considerazioni su archiviazione e prestazioni.

Il database stesso non controlla i suoi client e non si può presumere che i clienti inseriscano sempre in modo sicuro l'input dell'utente, anche se un database è progettato per essere utilizzato solo con un'applicazione .net che utilizza Entity Framework per incapsulare le transazioni e garantire query con parametri sono sistematicamente usati, non puoi saperlo che sarà sempre così.

Non saprei esattamente come farlo, ma creando tutti i campi di testo varchar(max), se un client ha problemi con le tabelle di Bobby e / o i parametri delle procedure memorizzate sono anchevarchar(max) , allora stai rendendo più facile per un attaccante trovare un valore di parametro valido ma abilmente malvagio che può fare cose che i clienti non dovrebbero fare - qualunque cosa sia.

Limitando la lunghezza a ciò di cui hai effettivamente bisogno, non ti stai proteggendo da questi attacchi intelligenti (non sono nemmeno sicuro di come si chiama in realtà, ricordo solo di averlo letto qualche tempo fa), ma non stai dicendo " vai avanti, prova a darmi uno script da 2 GB per l'esecuzione ".


Ciò che viene chiamato è probabilmente "injection" ("SQL injection", più specificamente).
Andriy M,

@AndriyM sì, per qualche ragione stavo pensando agli attacchi di troncamento SQL (la MS sembra aver rimosso il link che avevo aggiunto ai segnalibri), ma questo è fondamentalmente sfruttando i varchar(not-max)parametri, quindi mi sono bloccato un piede in bocca qui. Ma sì, l'iniezione SQL sarebbe applicabile qui. Forse dovrei riformulare un po 'questa risposta.
Mathieu Guindon,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.