Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Przechowywanie danych XML w SQL Server

Podczas pracy nad wydaniem dziennika transakcji dbForge, między innymi, nasz zespół musiał zastanowić się, jak prawidłowo przechowywać wpisane dane XML.

Na początek warto wspomnieć, że SQL Server nie przechowuje XML w formacie, w jakim został wprowadzony. Ciąg XML jest analizowany, dzielony na znaczniki, a zatem jest przechowywany w skompresowanym formacie. Elementy opisu, które serwer uważa za niepotrzebne, są odrzucane.

Należy również pamiętać, że jeśli typ danych kolumny jest określony jako prosty XML, serwer będzie przechowywać te dane jako ciągi Unicode.
Przykład 1.

CREATE TABLE XmlValuesTable (
  [uid] [int] IDENTITY PRIMARY KEY,
  v XML NOT NULL );
GO
INSERT INTO XmlValuesTable (v)
VALUES ('<note><float>123.456</float><time>01:23:45.789</time></note>');
INSERT INTO XmlValuesTable (v)
VALUES ('<note><float>4.0000000000</float><time>01:23:45Z</time></note>');

Serwer będzie przechowywać wstawkę dane w następujący sposób:

F0 04 6E006F0074006500 <- Name "note"
EF 000001 <- Namespace 01
F8 01 <- tag 01
F0 05 66006C006F0061007400 <- Name "float"
EF 000002 <- Namespace 02
F8 02 <- tag 02
11 07 3100320033002E00340035003600 <- string "123.456"
F7 <- closing tag
F0 04 740069006D006500 <- Name "time"
EF 000003 <- Namespace 02
F8 03 <- tag 03
11 0C 300031003A00320033003A00340035002E00370038003900 <- string "01:23:45.789"
F7 <- closing tag
F7 <- closing tag

W poniższym przykładzie typ danych kolumny jest określony jako wpisany przez XML Schema Collection.

Przykład 2.

CREATE XML SCHEMA COLLECTION [XmlValuesSchemaCollection_datetime2] AS
'<?xml version="1.0"?> 
<xsd:schema
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes"

  <xsd:element name="datetime2" type="sqltypes:datetime2"/> 
</xsd:schema>';
GO

CREATE TABLE XmlValuesTable_datetime2 (
  [uid] [int] IDENTITY PRIMARY KEY,
  v XML(XmlValuesSchemaCollection_datetime2) NOT NULL
);
GO

INSERT INTO XmlValuesTable_datetime2 (v)
VALUES (N'<datetime2>2014-06-18T06:39:05.190</datetime2>');
GO

W tym konkretnym przypadku serwer przechowa wstawkę dane w następujący sposób:

EA 09 014C010015 1A000000 <- type info 0x14C (332) “datetime2”, 0x15 (21) “dateTime” + offset
F0 09 6400610074006500740069006D0065003200 <- Name "datetime2"
EF 000001 <- Namespace 01
F8 01 <- tag 01
EA 05 004C010015 <- type info
7E 02978924A9380B <- "2014-06-18T06:39:05.190"
F7 <- closing tag

W ten sposób serwer konwertuje przechowywane dane na typy określone w dodatku do tego artykułu (listę wszystkich typów danych można zobaczyć, uruchamiając na serwerze zapytanie „select * from sys.xml_schema_types”).

Przyjrzyjmy się, jak serwer zapisze bardziej złożoną strukturę, podobną do tej w Przykładzie 1 i opisanej za pomocą XML Schema Collection.

Przykład 3.

CREATE XML SCHEMA COLLECTION [XmlValuesSchemaCollection] AS
'<?xml version="1.0"?>
<xsd:schema
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes"
  attributeFormDefault="unqualified" elementFormDefault="qualified"> 
  <xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes"
schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sql2008/sqltypes.xsd"/>

    <xsd:element name="note"> 
     <xsd:complexType> 
       <xsd:sequence> 
          <xsd:element name="float" type="xsd:float"/> 
          <xsd:element name="time" type="xsd:time"/> 
       </xsd:sequence> 
     </xsd:complexType> 
  </xsd:element> 
</xsd:schema>'; 
GO 

CREATE TABLE XmlValuesTable (
  [uid] [int] IDENTITY PRIMARY KEY,
  v XML(XmlValuesSchemaCollection) NOT NULL
);
GO

INSERT INTO XmlValuesTable (v)
VALUES ('<note><float>123.456</float><time>01:23:45.789</time></note>');

Serwer zapisze wstawkę dane w następujący sposób:

EA 05 0001000100 <- type info
F0 04 6E006F0074006500 <- Name "note"
EF 000001 <- Namespace
F8 01 <- tag 01
EA 09 0111000011 12000000 <- type info 0x11 (17) "float" + offset
F0 05 66006C006F0061007400 <- Name "float"
EF 000002 <- Namespace
F8 02 <- tag 02
EA 05 0011000011 <- type info 0x11 (17) "float"
03 79E9F642 <- "123.456"
F7 <- closing tag
EA 09 0116000016 10000000 <- type info 0x16 (22) "time" + offset
F0 04 740069006D006500 <- Name "time"
EF 000003 <- Namespace
F8 03 <- tag 03
EA 05 0016000016 <- type info 0x16 (22) "time"
7D 03FDAF4C005B950A <- "01:23:45.789"
F7 <- closing tag
F7 <- closing tag

Spróbujmy dodać link do schematu do wstawki.

Przykład 4.

INSERT INTO XmlValuesTable (v)
VALUES ('<note xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><float>123.456</float><time>01:23:45.789</time></note>');
EA 05 0001000100 <- type info
F0 04 6E006F0074006500 <- Name "note"
EF 000001 <- Namespace
F8 01 <- tag 01
F0 09 78006D006C006E0073003A00780073006900 <- Name "xmlns:xsi"
EF 000200 <- Namespace "xmlns:xsi"
F6 02 <- Attribute
11 29 68007400740070003A002F002F007700770077002E00770033002E006F00720067002F0032003000300031002F0058004D004C0053006300680065006D0061002D0069006E007300740061006E0063006500 <- "http://www.w3.org/2001/XMLSchema-instance"
F5 <- closing bracket
EA 09 0111000011 12000000 <- type info 0x11 (17) "float" + offset
F0 05 66006C006F0061007400 <- Name "float"
EF 000003 <- Namespace
F8 03 <- tag 03
EA 05 0011000011 <- type info 0x11 (17) "float"
03 79E9F642 <- "123.456"
F7 <- closing tag
EA 09 0116000016 10000000 <- type info 0x16 (22) "time" + offset
F0 04 740069006D006500  <- Name "time"
EF 000004 <- Namespace
F8 04 <- tag 08
EA 05 0016000016 <- type info 0x16 (22) "time"
7D 03FDAF4C005B950A <- "01:23:45.789"
F7 <- closing tag
F7 <- closing tag

Jak widać, serwer starannie zapisał przestrzeń nazw jako atrybut i wykorzystał na to prawie połowę miejsca, nawet pomimo tego, że przestrzeń nazw nie służy tutaj żadnemu użytecznemu celowi – dane zostały zapisane w taki sam sposób, w jaki byłyby zapisane bez przestrzeni nazw.

Wniosek

Z powyższego może się wydawać, że można zmniejszyć rozmiar bazy danych, przechowując niektóre typy danych (np. float) jako wpisane wartości, ponieważ 4 bajty wymagają znacznie mniej pamięci niż ta sama wartość zapisana jako ciąg Unicode. Należy jednak pamiętać, że dla każdej wartości używane jest dodatkowe 7-18 bajtów, aby opisać jej typ i przenieść ją do wymaganej pozycji.

Uzupełnienie

Korelacja typów XML, typów podstawowych i typów danych, których serwer używa do przechowywania wpisanych wartości.

Typ XML Typ podstawowy Przechowywany jako typ Rozmiar w bajtach
dowolny typ ciąg 2 * znaki
anySimpleType dowolny typ ciąg
ciąg anySimpleType ciąg
wartość logiczna anySimpleType wartość logiczna 1
pływający anySimpleType pływający 4
podwójny anySimpleType podwójne 8
dziesiętny anySimpleType SqlDecimal 20
czas trwania anySimpleType ciąg
dataGodzina anySimpleType *1
czas anySimpleType *1
data anySimpleType *1
gYearMonth anySimpleType ciąg
gRok anySimpleType ciąg
gMiesiącDzień anySimpleType ciąg
gDzień anySimpleType ciąg
gMiesiąc anySimpleType ciąg
szesnastkowy binarny anySimpleType tablica bajtów
base64Binary anySimpleType tablica bajtów
dowolny URI anySimpleType ciąg
QName anySimpleType ciąg
znormalizowany ciąg ciąg ciąg
token ciąg ciąg
język ciąg ciąg
Nazwa ciąg ciąg
Nazwa NC ciąg ciąg
ENTITY ciąg ciąg
NMTOKEN ciąg ciąg
liczba całkowita dziesiętny SqlDecimal 20
nonPositiveInteger liczba całkowita SqlDecimal 20
ujemna liczba całkowita nonPositiveInteger SqlDecimal 20
długi liczba całkowita SqlDecimal 20
int długi SqlDecimal 20
krótki int SqlDecimal 20
bajt krótki SqlDecimal 20
nonNegativeInteger liczba całkowita SqlDecimal 20
unsignedLong nonNegativeInteger SqlDecimal 20
unsignedInt unsignedLong SqlDecimal 20
unsignedShort unsignedInt SqlDecimal 20
unsignedByte unsignedShort SqlDecimal 20
dodatnia liczba całkowita nonNegativeInteger SqlDecimal 20
znak ciąg ciąg
nchar ciąg ciąg
varchar ciąg ciąg
nvarchar ciąg ciąg
tekst ciąg ciąg
ntext ciąg ciąg
zmienna base64Binary tablica bajtów
binarny base64Binary tablica bajtów
obraz base64Binary tablica bajtów
sygnatura czasowa base64Binary tablica bajtów
sygnatura czasowaNumeryczna długi SqlDecimal 20
liczbowe dziesiętny SqlDecimal 20
duży długi SqlDecimal 20
mały krótki SqlDecimal 20
tinyint unsignedByte SqlDecimal 20
bit wartość logiczna wartość logiczna 1
prawdziwe pływający pływający 4
data i godzina dataGodzina *1
smalldatetime dataGodzina *1
pieniądze dziesiętny SqlDecimal
małe pieniądze dziesiętny SqlDecimal
unikalny identyfikator dziesiętny ciąg
data/godzina2 dataGodzina *1
przesunięcie daty i godziny dataGodzina *1
hierarchid ciąg ciąg
obiektu dowolny URI ciąg

*1 – informacja o dacie/czasie. Konkretny typ jest zdefiniowany przez wartość.

Wartość Przechowywany jako typ Rozmiar w bajtach
Przesunięcie daty Data (liczba dni) 3
Przesunięcie daty (2019-09-16+02:00) Przesunięcie daty i godziny 11
Data i godzina DataGodzina 7-9 zależy od precyzji
Przesunięcie daty i godziny Przesunięcie daty i godziny 9
Czas DataGodzina 7-9 zależy od precyzji
Przesunięcie czasowe (01:23:45Z) Przesunięcie daty i godziny 9

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Grupuj DateTime w odstępach 5,15,30 i 60 minut

  2. Importuj wiele plików CSV do SQL Server z folderu

  3. 4 sposoby na uzyskanie listy harmonogramów w programie SQL Server Agent (T-SQL)

  4. Informacje o poleceniu GO w SQL Server

  5. Jak przedstawiać swoją wartość jako DBA dyrektorom finansowym