Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Si applica a: SQL Server 2016 (13.x) e versioni
successive Azure SQL Database
AzureSQL Managed Instance
SQL database in Microsoft Fabric
Il database SQL include funzioni JSON native che consentono di analizzare i documenti JSON usando il linguaggio SQL standard. È possibile archiviare documenti JSON nel motore di database SQL ed eseguire query sui dati JSON come in un database NoSQL. In questo articolo vengono descritte le opzioni per archiviare i documenti JSON.
Formato di archiviazione JSON
La prima decisione per la progettazione dell'archiviazione è la modalità di archiviazione dei documenti JSON nelle tabelle. Sono disponibili due opzioni:
- Archiviazione LOB: i documenti JSON possono essere archiviati così come sono in colonne con tipo di dati json o nvarchar. Questo è il modo migliore per eseguire rapidamente il caricamento e l'inserimento dei dati, perché la velocità di caricamento corrisponde alla velocità di caricamento delle colonne stringa. Questo approccio può introdurre un'ulteriore penalizzazione delle prestazioni sul tempo di esecuzione di query e analisi se non viene eseguita l'indicizzazione sui valori JSON, poiché devono essere analizzati i documenti JSON grezzi durante l'esecuzione delle query.
-
Archiviazione relazionale: i documenti JSON possono essere analizzati durante l'inserimento nella tabella usando le funzioni
OPENJSON,JSON_VALUEoJSON_QUERY. I frammenti dei documenti JSON di input possono essere archiviati nelle colonne contenenti elementi secondari JSON con tipo di dati json o nvarchar. Questo approccio aumenta il tempo di caricamento perché l'analisi JSON viene eseguita durante il caricamento, tuttavia le prestazioni delle query corrispondono a quelle delle query classiche sui dati relazionali. - Attualmente in SQL Server, JSON non è un tipo di dati predefinito.
Annotazioni
Tipo di dati JSON:
- è disponibile a livello generale per il database SQL di Azure e l'istanza gestita di SQL di Azure con SQL Server 2025 o Always-up-to-datecriteri di aggiornamento.
- è disponibile in anteprima per SQL Server 2025 (17.x) e il database SQL in Fabric.
Tabelle classiche
Il modo più semplice per archiviare i documenti JSON in SQL Server o nel database SQL di Azure consiste nel creare una tabella a due colonne contenente l'ID e il contenuto del documento. Per esempio:
create table WebSite.Logs (
[_id] bigint primary key identity,
[log] nvarchar(max)
);
In alternativa, se supportato:
create table WebSite.Logs (
[_id] bigint primary key identity,
[log] json
);
Questa struttura è equivalente alle raccolte che è possibile trovare nei database di documenti classici. La chiave primaria _id è un valore a incremento automatico che assicura un identificatore univoco per ogni documento e consente ricerche veloci. Questa struttura è una buona scelta in scenari NoSQL classici in cui si vuole recuperare un documento in base all'ID o aggiornarne uno archiviato in base all'ID.
- Usare il tipo di dati json nativo, dove disponibile per archiviare documenti JSON.
- Il tipo di dati nvarchar(max) consente di archiviare documenti JSON con una dimensione massima di 2 GB. Per motivi di prestazioni, se si è certi che i documenti JSON non superino le dimensioni di 8 KB, è tuttavia consigliabile usare nvarchar(4000) anziché nvarchar(max).
Nella tabella di esempio creata nell'esempio precedente si presuppone che nella colonna log vengano archiviati documenti JSON validi. Per assicurarsi che nella colonna log venga salvato contenuto JSON valido è possibile aggiungere un vincolo CHECK nella colonna. Per esempio:
ALTER TABLE WebSite.Logs
ADD CONSTRAINT [Log record should be formatted as JSON]
CHECK (ISJSON([log])=1)
Ogni volta che un utente inserisce o aggiorna un documento nella tabella, questo vincolo verifica che il documento JSON sia formattato correttamente. Senza il vincolo, la tabella è ottimizzata per gli inserimenti. I documenti JSON vengono infatti aggiunti direttamente alla colonna senza alcuna elaborazione.
Con i documenti JSON archiviati nella tabella, sarà possibile di usare il linguaggio Transact-SQL standard per eseguire query sui documenti. Per esempio:
SELECT TOP 100 JSON_VALUE([log], '$.severity'), AVG( CAST( JSON_VALUE([log],'$.duration') as float))
FROM WebSite.Logs
WHERE CAST( JSON_VALUE([log],'$.date') as datetime) > @datetime
GROUP BY JSON_VALUE([log], '$.severity')
HAVING AVG( CAST( JSON_VALUE([log],'$.duration') as float) ) > 100
ORDER BY AVG( CAST( JSON_VALUE([log],'$.duration') as float) ) DESC
La possibilità di usare qualsiasi funzione e clausola di query T-SQL per eseguire query sui documenti JSON è un enorme vantaggio. SQL Server e il database SQL non introducono alcun vincolo nelle query che è possibile usare per analizzare i documenti JSON. È possibile estrarre i valori da un documento JSON con la funzione JSON_VALUE e usarla nella query come qualsiasi altro valore.
Questa capacità di usare una sintassi di query T-SQL avanzata è la differenza principale tra SQL Server e il database SQL e i database NoSQL classici. Transact-SQL include probabilmente tutte le funzioni necessarie per elaborare i dati JSON.
Indexes
Se ci si rende conto che la ricerca nei documenti viene spesso eseguita in base a una proprietà (ad esempio, una proprietà severity in un documento JSON) è possibile aggiungere un indice non cluster rowstore nella proprietà per velocizzare le query.
È possibile creare una colonna calcolata che espone i valori JSON delle colonne JSON nel percorso specificato, ovvero nel percorso $.severity, e creare un indice standard in questa colonna calcolata. Per esempio:
create table WebSite.Logs (
[_id] bigint primary key identity,
[log] nvarchar(max),
[severity] AS JSON_VALUE([log], '$.severity'),
index ix_severity (severity)
);
La colonna calcolata usata in questo esempio è una colonna non persistente o virtuale che non aggiunge altro spazio alla tabella. Viene usata dall'indice ix_severity per migliorare le prestazioni delle query come nell'esempio seguente:
SELECT [log]
FROM Website.Logs
WHERE JSON_VALUE([log], '$.severity') = 'P4'
Una caratteristica importante di questo indice è che riconosce le regole di confronto. Se la colonna nvarchar originale include una proprietà COLLATION (ad esempio, distinzione tra maiuscole e minuscole o lingua giapponese), l'indice verrà organizzato in base alle regole della lingua o della distinzione tra maiuscole e minuscole associate alla colonna nvarchar. Questa conoscenza delle regole di confronto può rivelarsi importante se si sviluppano applicazioni per mercati globali che devono usare regole della lingua personalizzate durante l'elaborazione di documenti JSON.
Tabelle di grandi dimensioni e formato archivio a colonne
Se si prevede che la propria collezione includerà un numero elevato di documenti JSON, è consigliabile aggiungere un indice clustered columnstore nella raccolta, come illustrato nell'esempio seguente:
create sequence WebSite.LogID as bigint;
go
create table WebSite.Logs (
[_id] bigint default(next value for WebSite.LogID),
[log] nvarchar(max),
INDEX cci CLUSTERED COLUMNSTORE
);
Un indice clustered columnstore consente un'elevata compressione dei dati (fino a 25 volte) che può ridurre in modo significativo le esigenze di spazio di archiviazione, diminuire i costi di archiviazione e migliorare le prestazioni di I/O del carico di lavoro. Gli indici clustered columnstore sono inoltre ottimizzati per le scansioni di tabella e l'analisi nei documenti JSON, pertanto questo tipo di indice potrebbe essere l'opzione migliore per Log Analytics.
Nell'esempio precedente è stato usato un oggetto sequenza per assegnare i valori alla colonna _id. Sequenze e identità sono entrambe opzioni valide per la colonna ID.
Documenti modificati di frequente e tabelle ottimizzate per la memoria
Se nelle raccolte si prevedono numerose operazioni di aggiornamento, inserimento ed eliminazione è possibile archiviare i documenti JSON in tabelle ottimizzate per la memoria. Le raccolte JSON ottimizzate per la memoria mantengono sempre i dati in memoria, evitando il sovraccarico di I/O dell'archiviazione. Le raccolte JSON ottimizzate per la memoria non prevedono inoltre alcun tipo di blocco. Le azioni sui documenti non bloccano infatti le altre operazioni.
Per convertire una raccolta classica in una raccolta ottimizzata per la memoria è sufficiente specificare l'opzione WITH (MEMORY_OPTIMIZED=ON) dopo la definizione della tabella, come illustrato nell'esempio seguente. Si otterrà quindi una versione ottimizzata per la memoria della raccolta JSON.
CREATE TABLE WebSite.Logs (
[_id] bigint IDENTITY PRIMARY KEY NONCLUSTERED,
[log] nvarchar(max)
) WITH (MEMORY_OPTIMIZED=ON)
Una tabella ottimizzata per la memoria è l'opzione migliore per i documenti modificati di frequente. Quando si valuta l'uso di tabelle ottimizzate per la memoria è consigliabile tenere presente anche le prestazioni. Se possibile, usare nvarchar(4000) anziché nvarchar(max) per i documenti JSON presenti nelle raccolte ottimizzate per la memoria poiché le prestazioni potrebbero migliorare in modo significativo. Il tipo di dati json non è supportato con le tabelle ottimizzate per la memoria.
In modo analogo alle tabelle classiche, è possibile aggiungere indici sui campi esposti nelle tabelle ottimizzate per la memoria usando le colonne calcolate. Per esempio:
CREATE TABLE WebSite.Logs (
[_id] bigint IDENTITY PRIMARY KEY NONCLUSTERED,
[log] nvarchar(max),
[severity] AS cast(JSON_VALUE([log], '$.severity') as tinyint) persisted,
INDEX ix_severity (severity)
) WITH (MEMORY_OPTIMIZED=ON)
Per ottimizzare le prestazioni, effettuare il cast del valore JSON nel tipo più piccolo possibile utilizzabile per contenere il valore della proprietà. Nell'esempio precedente viene usato tinyint.
È possibile anche inserire le query SQL che aggiornano i documenti JSON nelle stored procedure per beneficiare della compilazione nativa. Per esempio:
CREATE PROCEDURE WebSite.UpdateData(@Id int, @Property nvarchar(100), @Value nvarchar(100))
WITH SCHEMABINDING, NATIVE_COMPILATION
AS BEGIN
ATOMIC WITH (transaction isolation level = snapshot, language = N'English')
UPDATE WebSite.Logs
SET [log] = JSON_MODIFY([log], @Property, @Value)
WHERE _id = @Id;
END
Questa procedura compilata in modo nativo accetta la query e crea il codice DLL che la esegue. Una procedura compilata in modo nativo è l'approccio più rapido per l'esecuzione di query e l'aggiornamento dei dati.
Conclusion
Le funzioni JSON native in SQL Server e nel database SQL consentono di elaborare i documenti JSON come nei database NoSQL. Per tutti i database, relazionali o NoSQL, esistono pro e contro in termini di elaborazione dei dati JSON. Il principale vantaggio dell'archiviazione di documenti JSON in SQL Server o nel database SQL è il supporto completo del linguaggio SQL. È possibile usare il linguaggio avanzato Transact-SQL per elaborare i dati e configurare una varietà di opzioni di archiviazione, dagli indici columnstore per la compressione elevata e l'analisi rapida alle tabelle ottimizzate per la memoria per l'elaborazione senza blocchi. Allo stesso tempo, si ottengono i vantaggi di una sicurezza avanzata e delle funzionalità di internazionalizzazione che sarà possibile riusare facilmente nello scenario NoSQL. I motivi descritti in questo articolo sono tutti ottimi motivi per prendere in considerazione l'archiviazione di documenti JSON in SQL Server o nel database SQL.
Altre informazioni su JSON nel motore di database SQL
Per un'introduzione visiva al supporto JSON predefinito, vedere i video seguenti:
- JSON as a bridge between NoSQL and relational worlds (JSON come ponte tra NoSQL e gli ambienti relazionali)