Domanda

Sto creando una tabella per tenere traccia della cronologia di oggetti particolari nel mio database. Attualmente ho le seguenti colonne:

HistoryId int IDENTITY(1,1) NOT NULL
HistoryDate datetimeoffset(7) NOT NULL 
HistoryTypeId int NOT NULL
HistoryDetails nvarchar(max) NULL

Per la maggior parte, ogni elemento della cronologia sarà autoesplicativo tramite HistoryTypeId, quindi HistoryDetails sarà Null o molto piccolo. Ma per un paio di tipi di cronologia, i dati dei dettagli saranno grandi. Va bene andare con nvarchar (max) per tutti i record o dovrei romperlo e avere una colonna aggiuntiva per i tipi di cronologia che richiederà più di 64 caratteri (vedi sotto)? Una stima approssimativa è che l'80% -90% dei record non richiederà più di 64 caratteri di informazioni dettagliate e ci saranno milioni di record nella tabella.

HistoryId int IDENTITY(1,1) NOT NULL
HistoryDate datetimeoffset(7) NOT NULL 
HistoryTypeId int NOT NULL
HistoryDetails nvarchar(64) NULL
HistoryDetailsMore nvarchar(max) NULL
È stato utile?

Soluzione

Non puoi rendere NVARCHAR (MAX) una parte di una chiave in un semplice indice B-Tree (puoi comunque usarlo come colonna inclusa in un indice) .

Altrimenti, l'archiviazione sarà la stessa fintanto che i dati nella colonna non supereranno la soglia della dimensione della riga.

Dato che probabilmente non indicherai comunque questo campo, è una buona idea crearlo come NVARCHAR (MAX) .

Anche se vuoi ancora indicizzarlo (diciamo, per fare ricerche con prefisso usando LIKE ), puoi creare una colonna calcolata NVARCHAR (450) , creare un indice su quella colonna e aggiungilo alle tue query per un filtro approssimativo.

Vedi questa voce nel mio blog per maggiori dettagli:

Se stai per fare ricerche esatte solo per le piccole colonne, crea una colonna calcolata, indicizzala e esegui una query in questo modo:

ALTER TABLE History ADD HistoryDetailsIndex AS SUBSTRING(HistoryDetails, 1, 50)

CREATE INDEX ix_mytable_typeid_details ON History (HistoryTypeId, HistoryDetailsIndex) INCLUDE (HistoryDetails)

SELECT  COUNT(*)
FROM    History
WHERE   HistoryTypeId = 123
        AND HistoryDetailsIndex LIKE 'string_prefix_up_to_50_characters%'
        AND HistoryDetails = 'string_prefix_up_to_50_characters_plus_everything_after_it'

Ciò includerà solo i primi 50 caratteri dal tuo HistoryDetails nella chiave indice (che verrà cercata in una condizione LIKE ) e tutto nella colonna inclusa.

Se sei assolutamente sicuro di non cercare mai una stringa che sia più lunga di 50 , puoi omettere la colonna inclusa e usare solo questa:

SELECT  COUNT(*)
FROM    History
WHERE   HistoryTypeId = 123
        AND HistoryDetailsIndex = 'string_prefix_up_to_50_characters'

Questo renderà più breve l'indice.

Tuttavia, ciò non riuscirà se fornisci una stringa più lunga di 50 , quindi usala se sei assolutamente sicuro di non cercare mai stringhe lunghe.

Altri suggerimenti

Dato che stai usando nvarchar, stai già pagando l'overhead del record di lunghezza variabile molto probabilmente, a meno che SQL Server non sovrascriva la lunghezza variabile per casi piccoli. Tuttavia, lo spazio su disco non dovrebbe cambiare per i record brevi tra nvarchar (64) e nvarchar (max). Dovrebbero occupare solo lo spazio necessario per adattare i propri dati. Normalmente quel numero verrebbe usato solo per limitare i dati. Se non vuoi vincolarlo, non dovresti pagare una penalità tra l'utilizzo di quei due che non stai già pagando.

Innanzitutto, tieni presente che varchar (MAX) può memorizzare fino a 2 GB di spazio, dietro le quinte utilizza effettivamente un valore TEXT, e successivamente utilizza più elaborazioni di varchar (8000) o meno.

Se si memorizzano molti dati più piccoli in un varchar (max), questi verranno trattati come una normale colonna varchar, a meno che non si superi 8000, dopo di che verranno trattati come un varchar (max).

La colonna è indicizzata o vuoi indicizzarla? In tal caso, evita il varchar (max).

Vorrei solo scegliere un valore più alto, dire varchar (255) e costringere gli utenti ad adattarsi al design del database e non viceversa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top