dbForgeトランザクションログのリリースに取り組んでいるとき、他のタスクの中でも、私たちのチームは、型指定されたXMLデータを適切に保存する方法をパズルで解く必要がありました。
まず、SQLServerは入力された形式でXMLを保存しないことに注意してください。 XML文字列は解析され、タグに分割されるため、圧縮形式で保存されます。サーバーが不要と見なす記述要素は破棄されます。
列のデータ型が単純なXMLとして指定されている場合、サーバーはこのデータをUnicode文字列として格納することにも注意してください。
例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>');
サーバーは挿入を保存します 次のようなデータ:
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
次の例では、列のデータ型はXMLスキーマコレクションを介して入力されたものとして指定されています。
例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
この特定のケースでは、サーバーは挿入を保存します 次のようなデータ:
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
このようにして、サーバーは保存されたデータをこの記事の補遺で指定されたタイプに変換します(サーバーで「select * fromsys.xml_schema_types」クエリを実行すると、すべてのデータタイプのリストを確認できます)。
サーバーが例1にあるような、XMLスキーマコレクションで説明されているようなより複雑な構造をどのように保存するかを見てみましょう。
例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>');
サーバーは挿入を保存します 次のようなデータ:
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
挿入物にスキーマリンクを追加してみましょう。
例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
ご覧のとおり、サーバーは名前空間を属性として慎重に保存し、名前空間がここでは実際には何の役にも立たないにもかかわらず、このためにほぼ半分のスペースを使用しました。データは同じように保存されました。名前空間なしで保存されます。
結論
上記のことから、4バイトはUnicode文字列として保存された同じ値よりも大幅に少ないストレージを必要とするため、一部のデータ型(floatなど)を型付き値として保存することでデータベースのサイズを縮小できるように思われるかもしれません。ただし、タイプを記述して必要な位置に移動するために、各値に7〜18バイトが追加で使用されることに注意してください。
補遺
サーバーが型付きの値を格納するために使用するXMLタイプ、基本タイプ、およびデータ型の相関関係。
XMLタイプ | 基本タイプ | タイプとして保存 | バイト単位のサイズ | |
anyType | 文字列 | 2*文字 | ||
anySimpleType | anyType | 文字列 | ||
文字列 | anySimpleType | 文字列 | ||
ブール値 | anySimpleType | ブール値 | 1 | |
フロート | anySimpleType | フロート | 4 | |
ダブル | anySimpleType | ダブル | 8 | |
10進数 | anySimpleType | SqlDecimal | 20 | |
期間 | anySimpleType | 文字列 | ||
dateTime | anySimpleType | * 1 | ||
時間 | anySimpleType | * 1 | ||
日付 | anySimpleType | * 1 | ||
gYearMonth | anySimpleType | 文字列 | ||
gYear | anySimpleType | 文字列 | ||
gMonthDay | anySimpleType | 文字列 | ||
gDay | anySimpleType | 文字列 | ||
gMonth | anySimpleType | 文字列 | ||
hexBinary | anySimpleType | バイトの配列 | ||
base64Binary | anySimpleType | バイトの配列 | ||
anyURI | anySimpleType | 文字列 | ||
QName | anySimpleType | 文字列 | ||
normalizedString | 文字列 | 文字列 | ||
トークン | 文字列 | 文字列 | ||
言語 | 文字列 | 文字列 | ||
名前 | 文字列 | 文字列 | ||
NCName | 文字列 | 文字列 | ||
エンティティ | 文字列 | 文字列 | ||
NMTOKEN | 文字列 | 文字列 | ||
整数 | 10進数 | SqlDecimal | 20 | |
nonPositiveInteger | 整数 | SqlDecimal | 20 | |
negativeInteger | nonPositiveInteger | SqlDecimal | 20 | |
長い | 整数 | SqlDecimal | 20 | |
int | 長い | SqlDecimal | 20 | |
短い | int | SqlDecimal | 20 | |
バイト | 短い | SqlDecimal | 20 | |
nonNegativeInteger | 整数 | SqlDecimal | 20 | |
unsignedLong | nonNegativeInteger | SqlDecimal | 20 | |
unsignedInt | unsignedLong | SqlDecimal | 20 | |
unsignedShort | unsignedInt | SqlDecimal | 20 | |
unsignedByte | unsignedShort | SqlDecimal | 20 | |
positiveInteger | nonNegativeInteger | SqlDecimal | 20 | |
char | 文字列 | 文字列 | ||
nchar | 文字列 | 文字列 | ||
varchar | 文字列 | 文字列 | ||
nvarchar | 文字列 | 文字列 | ||
テキスト | 文字列 | 文字列 | ||
ntext | 文字列 | 文字列 | ||
varbinary | base64Binary | バイトの配列 | ||
バイナリ | base64Binary | バイトの配列 | ||
画像 | base64Binary | バイトの配列 | ||
タイムスタンプ | base64Binary | バイトの配列 | ||
timestampNumeric | 長い | SqlDecimal | 20 | |
数値 | 10進数 | SqlDecimal | 20 | |
bigint | 長い | SqlDecimal | 20 | |
smallint | 短い | SqlDecimal | 20 | |
tinyint | unsignedByte | SqlDecimal | 20 | |
ビット | ブール値 | ブール値 | 1 | |
本物 | フロート | フロート | 4 | |
datetime | dateTime | * 1 | ||
smalldatetime | dateTime | * 1 | ||
お金 | 10進数 | SqlDecimal | ||
smallmoney | 10進数 | SqlDecimal | ||
一意の識別子 | 10進数 | 文字列 | ||
datetime2 | dateTime | * 1 | ||
datetimeoffset | dateTime | * 1 | ||
hierarchyid | 文字列 | 文字列 | ||
dbobject | anyURI | 文字列 |
* 1 –データ/時間情報。特定のタイプは値によって定義されます。
値 | タイプとして保存 | バイト単位のサイズ |
DateOffset | 日付(日数) | 3 |
DateOffset(2019-09-16 + 02:00) | DateTimeOffset | 11 |
DateTime | DateTime | 7-9は精度に依存します |
DateTimeOffset | DateTimeOffset | 9 |
時間 | DateTime | 7-9は精度に依存します |
TimeOffset(01:23:45Z) | DateTimeOffset | 9 |