Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Memorizzazione di dati XML in SQL Server

Durante il lavoro sul rilascio di dbForge Transaction Log, tra le altre attività, il nostro team ha dovuto capire come archiviare correttamente i dati XML digitati.

Per cominciare, vale la pena ricordare che SQL Server non archivia XML nel formato in cui è stato inserito. Una stringa XML viene analizzata, divisa in tag e quindi archiviata in un formato compresso. Gli elementi descrittivi che il server considera non necessari vengono eliminati.

Bisogna inoltre tenere presente che, se il tipo di dati di una colonna è specificato come XML semplice, il server memorizzerà questi dati come stringhe Unicode.
Esempio 1.

CREATE TABLE XmlValuesTable ( [uid] [int] IDENTITY PRIMARY KEY, v XML NOT NULL );GOINSERT INTO XmlValuesTable (v)VALUES ('123.456');INSERT INTO XmlValuesTable (v)VALUES ('4.0000000000');

Il server memorizzerà l'inserto dati come segue:

; F7 <- tag di chiusuraF0 04 740069006D006500 <- Nome "time"EF 000003 <- Spazio dei nomi 02F8 03 <- tag 0311 0C 300031003A00320033003A00340035002E00370038003900 <- string "01:8- tag di chiusura F7-29:45 <7.

Nell'esempio seguente, il tipo di dati della colonna viene specificato come digitato tramite XML Schema Collection.

Esempio 2.

CREA RACCOLTA SCHEMA XML [XmlValuesSchemaCollection_datetime2] AS'  ';GOCREATE TABLE XmlValuesTable_datetime2 ( [uid] [ int] IDENTITY PRIMARY KEY, v XML(XmlValuesSchemaCollection_datetime2) NOT NULL);GOINSERT INTO XmlValuesTable_datetime2 (v)VALUES (N'2014-06-18T06:39:05.190');GO

In questo caso particolare, il server memorizzerà l'inserto dati come segue:

; - digitare info7E 02978924A9380B <- "2014-06-18T06:39:05.190"F7 <- tag di chiusura

In questo modo, il server converte i dati archiviati nei tipi specificati nell'addendum a questo articolo (è possibile visualizzare l'elenco di tutti i tipi di dati eseguendo la query "select * from sys.xml_schema_types" sul server).

Diamo un'occhiata a come il server salverà una struttura più complessa simile a quella dell'Esempio 1 e descritta con XML Schema Collection.

Esempio 3.

CREA RACCOLTA SCHEMA XML [XmlValuesSchemaCollection] AS'          '; GO CREATE TABLE XmlValuesTable ( [uid] [int] IDENTITY PRIMARY KEY, v XML(XmlValuesSchemaCollection) NOT NULL);GOINSERT INTO XmlValuesTable (v)VALUES ('123.456');

Il server salverà l'inserto dati come segue:

EA 05 0001000100 <- type infoF0 04 6E006F0074006500 <- Nome "note"EF 000001 <- NamespaceF8 01 <- tag 01EA 09 0111000011 12000000 <- type info 0x11 (17) "float" + offsetF0 "07 6001-F0" C000 6600 float"EF 000002 <- NamespaceF8 02 <- tag 02EA 05 0011000011 <- type info 0x11 (17) "float"03 79E9F642 <- "123.456"F7 <- tag di chiusuraEA 09 0116000016 10000000 <- type info 0x16 (22) "time " + offsetF0 04 740069006D006500 <- Nome "tempo"EF 000003 <- Spazio dei nomiF8 03 <- tag 03EA 05 0016000016 <- tipo info 0x16 (22) "tempo"7D 03FDAF4C005B950A <- "01:23:45.789"F7 <- tag di chiusuraF7 <- tag di chiusura

Proviamo ad aggiungere un collegamento schema all'inserto.

Esempio 4.

INSERT INTO XmlValuesTable (v)VALUES ('123.456');
; <- Attribute11 29 68007400740070003A002F002F007700770077002E00770033002E006F00720067002F0032003000300031002F0058004D004C0053006300680065006D0061002D0069006E007300740061006E0063006500 <- "http://www.w3.org/2001/XMLSchema-instance"F5 <- closing bracketEA 09 0111000011 12000000 <- type info 0x11 (17) "float" + offsetF0 05 66006C006F0061007400 <- Name "float"EF 000003 <- NamespaceF8 03 <- tag 03EA 05 0011000011 <- type info 0x11 (17) "float"03 79E9F642 <- "123.456"F7 <- chiusura tagEA 09 0116000016 10000000 <- type info 0x16 (22) " time" + offsetF0 04 740069006D006500 <- Nome "time"EF 000004 <- NamespaceF8 04 <- tag 08EA 05 0016000016 <- type info 0x16 (22) "time"7D 03FDAF4C005B950A <- "01:23:45.789"F7 <- chiusura tagF7 <- tag di chiusura

Come puoi vedere, il server ha salvato con cura lo spazio dei nomi come attributo e ha utilizzato quasi la metà dello spazio per questo anche nonostante il fatto che lo spazio dei nomi non serva a nessuno scopo utile qui:i dati sono stati salvati nello stesso modo in cui sarebbero salvato senza lo spazio dei nomi.

Conclusione

Da quanto sopra, può sembrare che sia possibile ridurre le dimensioni di un database archiviando alcuni tipi di dati (ad es. float) come valori tipizzati poiché 4 byte richiedono uno spazio di archiviazione notevolmente inferiore rispetto allo stesso valore salvato come stringa Unicode. Tuttavia, dovresti tenere presente che per ogni valore vengono utilizzati 7-18 byte aggiuntivi per descriverne il tipo e spostarlo nella posizione necessaria.

Addendum

Correlazione di tipi XML, tipi di base e tipi di dati utilizzati dal server per memorizzare i valori tipizzati.

Tipo XML Tipo di base Memorizzato come tipo Dimensioni in byte
qualsiasiTipo stringa 2 * caratteri
qualsiasiTipoSimple qualsiasiTipo stringa
stringa qualsiasiTipoSimple stringa
booleano qualsiasiTipoSimple booleano 1
galleggiante qualsiasiTipoSimple galleggiante 4
doppio qualsiasiTipoSimple doppio 8
decimale qualsiasiTipoSimple SqlDecimale 20
durata qualsiasiTipoSimple stringa
dateTime qualsiasiTipoSimple *1
tempo qualsiasiTipoSimple *1
data qualsiasiTipoSimple *1
gAnnoMese qualsiasiTipoSimple stringa
gAnno qualsiasiTipoSimple stringa
gMonthDay qualsiasiTipoSimple stringa
gDay qualsiasiTipoSimple stringa
gMese qualsiasiTipoSimple stringa
hexBinary qualsiasiTipoSimple matrice di byte
base64Binario qualsiasiTipoSimple matrice di byte
qualsiasiURI qualsiasiTipoSimple stringa
QName qualsiasiTipoSimple stringa
stringa normalizzata stringa stringa
token stringa stringa
lingua stringa stringa
Nome stringa stringa
NomeNC stringa stringa
ENTITÀ stringa stringa
NMTOKEN stringa stringa
numero intero decimale SqlDecimale 20
Intero nonpositivo intero SqlDecimale 20
Intero negativo Intero nonpositivo SqlDecimale 20
lungo intero SqlDecimale 20
int lungo SqlDecimale 20
breve int SqlDecimale 20
byte breve SqlDecimale 20
Intero non negativo intero SqlDecimale 20
unsignedLong Intero non negativo SqlDecimale 20
unsignedInt unsignedLong SqlDecimale 20
unsignedShort unsignedInt SqlDecimale 20
unsignedByte unsignedShort SqlDecimale 20
Intero positivo Intero non negativo SqlDecimale 20
carattere stringa stringa
nchar stringa stringa
varchar stringa stringa
nvarchar stringa stringa
testo stringa stringa
ntext stringa stringa
variabile base64Binario matrice di byte
binario base64Binario matrice di byte
immagine base64Binario matrice di byte
indicatore orario base64Binario matrice di byte
timestampNumerico lungo SqlDecimale 20
numerico decimale SqlDecimale 20
bigint lungo SqlDecimale 20
smallint breve SqlDecimale 20
tinyint unsignedByte SqlDecimale 20
bit booleano booleano 1
reale galleggiante galleggiante 4
dataora dataOra *1
smalldatetime dataOra *1
soldi decimale SqlDecimale
piccoli soldi decimale SqlDecimale
identificatore univoco decimale stringa
dataora2 dataOra *1
datatimeoffset dataOra *1
ID gerarchico stringa stringa
dbooggetto qualsiasiURI stringa

*1 – informazioni su dati/ora. Il tipo specifico è definito dal valore.

Valore Memorizzato come tipo Dimensioni in byte
Offset data Data (numero di giorni) 3
DateOffset (2019-09-16+02:00) DateTimeOffset 11
DataOra DataOra 7-9 dipende dalla precisione
DateTimeOffset DateTimeOffset 9
Tempo DataOra 7-9 dipende dalla precisione
TimeOffset (01:23:45Z) DateTimeOffset 9