Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Armazenando dados XML no SQL Server


Ao trabalhar no lançamento do dbForge Transaction Log, entre outras tarefas, nossa equipe teve que descobrir como armazenar corretamente os dados XML digitados.

Para começar, vale ressaltar que o SQL Server não armazena XML no formato em que foi inserido. Uma string XML é analisada, dividida em tags e, portanto, armazenada em um formato compactado. Os elementos de descrição que o servidor considera desnecessários são descartados.

Também deve-se ter em mente que, se o tipo de dado de uma coluna for especificado como XML simples, o servidor armazenará esses dados como strings Unicode.
Exemplo 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');

O servidor armazenará o inserir dados da seguinte forma:
 f0 04 6E006F0074006500 <- Nome "Nota" EF 000001 <- Namespace 01F8 01 <- Tag 01f0 05 66006C006F0061007400 <- Nome "Float" EF 000002 <- Namespace 02f8 02 <-Tag F7 <- tag de fechamentoF0 04 740069006D006500 <- Name "time"EF 000003 <- Namespace 02F8 03 <- tag 0311 0C 300031003A00320033003A00340035002E00370038003900 <- tag de fechamento "F7 <-23:45. 
No exemplo a seguir, o tipo de dados da coluna é especificado conforme digitado por meio da Coleção de Esquemas XML.

Exemplo 2.
CRIAR COLEÇÃO DE ESQUEMAS 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

Neste caso específico, o servidor armazenará o inserir dados da seguinte forma:
 ea 09 014C010015 1A000000 <- Digite informações 0x14C (332) “DateTime2”, 0x15 (21) “DateTime” + OFFSETF0 09 640061007006500740069006D0065003200 <- Nome ” - digite info7E 02978924A9380B <- "2014-06-18T06:39:05.190"F7 <- tag de fechamento

Dessa forma, o servidor converte os dados armazenados em tipos especificados no adendo deste artigo (você pode ver a lista de todos os tipos de dados executando a consulta “select * from sys.xml_schema_types” no servidor).

Vamos dar uma olhada em como o servidor salvará uma estrutura mais complexa semelhante à do Exemplo 1 e descrita com XML Schema Collection.

Exemplo 3.
CRIAR COLEÇÃO DE ESQUEMAS XML [XmlValuesSchemaCollection] AS'          '; GO CREATE TABLE XmlValuesTable ( [uid] [int] IDENTITY PRIMARY KEY, v XML(XmlValuesSchemaCollection) NOT NULL);GOINSERT INTO XmlValuesTable (v)VALUES ('123.456');

O servidor salvará o inserir dados da seguinte forma:
EA 05 0001000100 <- type infoF0 04 6E006F0074006500 <- Name "note"EF 000001 <- NamespaceF8 01 <- tag 01EA 09 0111000011 12000000 <- type info 0x11 (17) "float" + offsetF0 040 660 Name float"EF 000002 <- NamespaceF8 02 <- tag 02EA 05 0011000011 <- type info 0x11 (17) "float"03 79E9F642 <- "123.456"F7 <- fechamento tagEA 09 0116000016 10000000 <- type info 0x16 (22) "time " + offsetF0 04 740069006D006500 <- Nome "time"EF 000003 <- NamespaceF8 03 <- tag 03EA 05 0016000016 <- tipo info 0x16 (22) "time"7D 03FDAF4C005B950A <- "01:23:45.789"F7 <- fechando tagF7 <- tag de fechamento

Vamos tentar adicionar um link de esquema ao insert.

Exemplo 4.
INSERT INTO XmlValuesTable (v)VALUES ('123.456');
EA 05 0001000100 <- type infoF0 04 6E006F0074006500 <- Name "note"EF 000001 <- NamespaceF8 01 <- tag 01F0 09 78006D006C006E0073003A00780073006900 <- Name "xmlns:xsi"EF 000200 <- Namespace "xmlns:xsi"F6 02 <- 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 <- fechando tagEA 09 0116000016 10000000 <- type info 0x16 (22) " time" + offsetF0 04 740069006D006500 <- Nome "time"EF 000004 <- NamespaceF8 04 <- tag 08EA 05 0016000016 <- tipo info 0x16 (22) "time"7D 03FDAF4C005B950A <- "01:23:45.789"F7 <- fechamento tagF7 <- tag de fechamento

Como você pode ver, o servidor salvou cuidadosamente o namespace como um atributo e usou quase metade do espaço para isso, apesar do fato de que o namespace não serve para nenhum propósito útil aqui - os dados foram salvos da mesma maneira que seriam salvo sem o namespace.

Conclusão


Pelo exposto, pode parecer que você pode reduzir o tamanho de um banco de dados armazenando alguns tipos de dados (por exemplo, float) como valores digitados, pois 4 bytes exigem muito menos armazenamento do que o mesmo valor salvo como uma string Unicode. No entanto, você deve ter em mente que 7-18 bytes adicionais são usados ​​para cada valor para descrever seu tipo e movê-lo para a posição necessária.

Adendo


Correlação de tipos XML, tipos base e tipos de dados que o servidor usa para armazenar valores tipados.


Tipo XML Tipo base Armazenado como tipo Tamanho em bytes
qualquer tipo cadeia 2 * caracteres
anySimpleType qualquer tipo cadeia
cadeia anySimpleType cadeia
booleano anySimpleType booleano 1
flutuar anySimpleType flutuar 4
duplo anySimpleType duplo 8
decimal anySimpleType SqlDecimal 20
duração anySimpleType cadeia
dataHora anySimpleType *1
hora anySimpleType *1
data anySimpleType *1
gAnoMês anySimpleType cadeia
gAno anySimpleType cadeia
gMonthDay anySimpleType cadeia
gDia anySimpleType cadeia
gMonth anySimpleType cadeia
hexBinary anySimpleType matriz de bytes
base64Binary anySimpleType matriz de bytes
qualquer URI anySimpleType cadeia
QName anySimpleType cadeia
normalizedString cadeia cadeia
token cadeia cadeia
idioma cadeia cadeia
Nome cadeia cadeia
NCName cadeia cadeia
ENTIDADE cadeia cadeia
NMTOKEN cadeia cadeia
inteiro decimal SqlDecimal 20
nonPositiveInteger inteiro SqlDecimal 20
negativeInteger nonPositiveInteger SqlDecimal 20
longo inteiro SqlDecimal 20
int longo SqlDecimal 20
curta int SqlDecimal 20
byte curta SqlDecimal 20
nonNegativeInteger inteiro SqlDecimal 20
unsignedLong nonNegativeInteger SqlDecimal 20
unsignedInt unsignedLong SqlDecimal 20
unsignedShort unsignedInt SqlDecimal 20
unsignedByte unsignedShort SqlDecimal 20
positivoInteger nonNegativeInteger SqlDecimal 20
caractere cadeia cadeia
nchar cadeia cadeia
varchar cadeia cadeia
nvarchar cadeia cadeia
texto cadeia cadeia
ntext cadeia cadeia
varbinário base64Binary matriz de bytes
binário base64Binary matriz de bytes
imagem base64Binary matriz de bytes
carimbo de data e hora base64Binary matriz de bytes
timestampNumeric longo SqlDecimal 20
numérico decimal SqlDecimal 20
grande longo SqlDecimal 20
pequeno curta SqlDecimal 20
tinyint unsignedByte SqlDecimal 20
bit booleano booleano 1
real flutuar flutuar 4
datahora dataHora *1
smalldatetime dataHora *1
dinheiro decimal SqlDecimal
dinheiro pequeno decimal SqlDecimal
identificador exclusivo decimal cadeia
datahora2 dataHora *1
deslocamento de data e hora dataHora *1
hierarquia cadeia cadeia
dbobject qualquer URI cadeia

*1 – informação de dados/hora. O tipo específico é definido pelo valor.
Valor Armazenado como tipo Tamanho em bytes
DateOffset Data (quantidade de dias) 3
DateOffset (2019-09-16+02:00) DateTimeOffset 11
DataHora DataHora 7-9 depende da precisão
DateTimeOffset DateTimeOffset 9
Hora DataHora 7-9 depende da precisão
TimeOffset (01:23:45Z) DateTimeOffset 9