Khi làm việc trên bản phát hành Nhật ký giao dịch dbForge, trong số các nhiệm vụ khác, nhóm của chúng tôi phải tìm cách lưu trữ dữ liệu XML đã nhập đúng cách.
Để bắt đầu, điều đáng nói là SQL Server không lưu trữ XML ở định dạng mà nó đã được nhập. Một chuỗi XML được phân tích cú pháp, phân tách thành các thẻ và do đó được lưu trữ ở định dạng nén. Các phần tử mô tả mà máy chủ cho là không cần thiết sẽ bị loại bỏ.
Cũng cần lưu ý rằng, nếu kiểu dữ liệu của một cột được chỉ định là XML đơn giản, máy chủ sẽ lưu trữ dữ liệu này dưới dạng chuỗi Unicode.
Ví dụ 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>');
Máy chủ sẽ lưu trữ insert dữ liệu như sau:
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
Trong ví dụ sau, kiểu dữ liệu cột được chỉ định như được nhập thông qua Bộ sưu tập lược đồ XML.
Ví dụ 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
Trong trường hợp cụ thể này, máy chủ sẽ lưu trữ insert dữ liệu như sau:
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
Theo cách này, máy chủ chuyển đổi dữ liệu được lưu trữ thành các loại được chỉ định trong phụ lục của bài viết này (bạn có thể xem danh sách tất cả các loại dữ liệu bằng cách chạy truy vấn “select * from sys.xml_schema_types” trên máy chủ).
Hãy xem cách máy chủ sẽ lưu một cấu trúc phức tạp hơn tương tự như cấu trúc trong Ví dụ 1 và được mô tả bằng Bộ sưu tập lược đồ XML.
Ví dụ 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>');
Máy chủ sẽ lưu insert dữ liệu như sau:
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
Hãy thử thêm một liên kết giản đồ vào phần chèn.
Ví dụ 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
Như bạn có thể thấy, máy chủ đã cẩn thận lưu không gian tên dưới dạng thuộc tính và sử dụng gần một nửa không gian cho việc này mặc dù thực tế là không gian tên không thực sự phục vụ bất kỳ mục đích hữu ích nào ở đây - dữ liệu đã được lưu giống như cách nó sẽ diễn ra. được lưu mà không có vùng tên.
Kết luận
Từ những điều trên, có vẻ như bạn có thể giảm kích thước của cơ sở dữ liệu bằng cách lưu trữ một số kiểu dữ liệu (ví dụ:float) dưới dạng giá trị đã nhập vì 4 byte yêu cầu dung lượng ít hơn đáng kể so với cùng một giá trị được lưu dưới dạng chuỗi Unicode. Tuy nhiên, bạn nên nhớ rằng 7-18 byte bổ sung được sử dụng cho mỗi giá trị để mô tả kiểu của nó và di chuyển nó đến vị trí cần thiết.
Phụ lục
Mối tương quan của các kiểu XML, kiểu cơ sở và kiểu dữ liệu mà máy chủ sử dụng để lưu trữ các giá trị đã nhập.
Loại XML | Loại cơ sở | Được lưu trữ dưới dạng loại | Kích thước tính bằng byte | |
anyType | chuỗi | 2 * ký tự | ||
anySimpleType | anyType | chuỗi | ||
chuỗi | anySimpleType | chuỗi | ||
boolean | anySimpleType | boolean | 1 | |
float | anySimpleType | float | 4 | |
gấp đôi | anySimpleType | gấp đôi | 8 | |
thập phân | anySimpleType | SqlDecimal | 20 | |
thời lượng | anySimpleType | chuỗi | ||
dateTime | anySimpleType | * 1 | ||
thời gian | anySimpleType | * 1 | ||
ngày | anySimpleType | * 1 | ||
gYearMonth | anySimpleType | chuỗi | ||
gYear | anySimpleType | chuỗi | ||
gMonthDay | anySimpleType | chuỗi | ||
gDay | anySimpleType | chuỗi | ||
gMonth | anySimpleType | chuỗi | ||
hexBinary | anySimpleType | mảng byte | ||
base64Binary | anySimpleType | mảng byte | ||
anyURI | anySimpleType | chuỗi | ||
QName | anySimpleType | chuỗi | ||
normalizedString | chuỗi | chuỗi | ||
mã thông báo | chuỗi | chuỗi | ||
ngôn ngữ | chuỗi | chuỗi | ||
Tên | chuỗi | chuỗi | ||
NCName | chuỗi | chuỗi | ||
ENTITY | chuỗi | chuỗi | ||
NMTOKEN | chuỗi | chuỗi | ||
số nguyên | thập phân | SqlDecimal | 20 | |
nonPositiveInteger | số nguyên | SqlDecimal | 20 | |
negativeInteger | nonPositiveInteger | SqlDecimal | 20 | |
dài | số nguyên | SqlDecimal | 20 | |
int | dài | SqlDecimal | 20 | |
ngắn | int | SqlDecimal | 20 | |
byte | ngắn | SqlDecimal | 20 | |
nonNegativeInteger | số nguyên | SqlDecimal | 20 | |
unsignedLong | nonNegativeInteger | SqlDecimal | 20 | |
unsignedInt | unsignedLong | SqlDecimal | 20 | |
unsignedShort | unsignedInt | SqlDecimal | 20 | |
unsignedByte | unsignedShort | SqlDecimal | 20 | |
positiveInteger | nonNegativeInteger | SqlDecimal | 20 | |
ký tự | chuỗi | chuỗi | ||
nchar | chuỗi | chuỗi | ||
varchar | chuỗi | chuỗi | ||
nvarchar | chuỗi | chuỗi | ||
văn bản | chuỗi | chuỗi | ||
ntext | chuỗi | chuỗi | ||
varbinary | base64Binary | mảng byte | ||
nhị phân | base64Binary | mảng byte | ||
hình ảnh | base64Binary | mảng byte | ||
dấu thời gian | base64Binary | mảng byte | ||
timestampNumeric | dài | SqlDecimal | 20 | |
số | thập phân | SqlDecimal | 20 | |
bigint | dài | SqlDecimal | 20 | |
smallint | ngắn | SqlDecimal | 20 | |
tinyint | unsignedByte | SqlDecimal | 20 | |
bit | boolean | boolean | 1 | |
thực | float | float | 4 | |
ngày giờ | dateTime | * 1 | ||
smalldatetime | dateTime | * 1 | ||
tiền | thập phân | SqlDecimal | ||
smallmoney | thập phân | SqlDecimal | ||
uniqueidentifier | thập phân | chuỗi | ||
datetime2 | dateTime | * 1 | ||
datetimeoffset | dateTime | * 1 | ||
phân cấp | chuỗi | chuỗi | ||
dbobject | anyURI | chuỗi |
* 1 - thông tin dữ liệu / thời gian. Loại cụ thể được xác định bởi giá trị.
Giá trị | Được lưu trữ dưới dạng loại | Kích thước tính bằng byte |
DateOffset | Ngày (số ngày) | 3 |
DateOffset (2019-09-16 + 02:00) | DateTimeOffset | 11 |
DateTime | DateTime | 7-9 phụ thuộc vào độ chính xác |
DateTimeOffset | DateTimeOffset | 9 |
Thời gian | DateTime | 7-9 phụ thuộc vào độ chính xác |
TimeOffset (01:23:45Z) | DateTimeOffset | 9 |