Mal*_*lex 5 schema database-design sql-server
我有一个拥有数百万个实例的实体。每个实例都必须引用一个有序的项目列表。列表必须是唯一的,因此不会多次存储列表。但是一旦创建,列表和实体实例都是不可变的。实体实例将远多于列表,并且数据库必须支持实体的快速插入。
那么,什么是插入高效、健壮、存储不可变、唯一、有序列表的方式?
编辑:列表项是简单的整数,典型长度约为 5 项。一长串的清单,比如 10 或 20 个项目是不太可能的,但可能。
编辑:到目前为止,我已经考虑过这些方法:
1)
lists
表有这些列:<list_id> <order> <item>
所以如果列表 #5 包含[10,20,30]
表将包含的元素:
5 1 10
5 2 20
5 3 30
Run Code Online (Sandbox Code Playgroud)
实体表将有一个item_list_id
引用该lists
表的列(它不是外键,因为list_id
它不是lists
表中的唯一列-这可以通过添加另一个包含所有有效列的表来解决list_ids
)。
2)
lists
表有这些列:<list_id> <item1> <item2> <item3> ... <itemN>
所以如果列表 #5 包含[10,20,30]
表将包含的元素:
5 10 20 30
Run Code Online (Sandbox Code Playgroud)
实体表将有一item_list_id
列引用该lists
表。
3)
使用解决方案#1,但将无意义的替换为list_id
序列化形式的列表中的散列(比如 SHA-1)。
您可能可以使用 XML 数据类型来存储列表。这样,您也可以保留顺序。尚未进行任何广泛的性能测试,但对于类型化 XML(架构)和列上的 XML 索引,这可能适合您。
至于插入性能,这种方法的一个优点是您只需向单个表中进行插入,这减少了许多死锁和争用问题的风险,特别是在事务中。
创建 XML 架构:
CREATE XML SCHEMA COLLECTION dbo.itemlist AS '
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="list">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="item" type="xsd:int" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>';
Run Code Online (Sandbox Code Playgroud)
创建具有类型化 XML 列的表:
CREATE TABLE dbo.instances (
instance_id int IDENTITY(1, 1) NOT NULL,
list xml(itemlist) NOT NULL,
PRIMARY KEY CLUSTERED (instance_id)
);
Run Code Online (Sandbox Code Playgroud)
创建 XML 索引:
CREATE PRIMARY XML INDEX IX_instances_list
ON dbo.instances (list);
Run Code Online (Sandbox Code Playgroud)
一些示例数据,大约一百万行左右:
INSERT INTO dbo.instances (list) VALUES ('<list><item>1</item><item>2</item><item>3</item></list>');
WHILE (@@ROWCOUNT<500000)
INSERT INTO dbo.instances (list)
SELECT '<list><item>'+CAST(CAST(1000*RAND(10+instance_id) AS int) AS varchar(10))+
'</item><item>'+CAST(CAST(1000*RAND(20+instance_id) AS int) AS varchar(10))+
'</item><item>'+CAST(CAST(1000*RAND(30+instance_id) AS int) AS varchar(10))+
'</item></list>'
FROM dbo.instances;
Run Code Online (Sandbox Code Playgroud)
以下是提取数据的方法:
SELECT i.instance_id,
listitem.x.value('.', 'int') AS item
FROM dbo.instances AS i WITH (NOLOCK)
CROSS APPLY i.list.nodes('/list/item') AS listitem(x);
Run Code Online (Sandbox Code Playgroud)
...但是,除非提供子句,否则无法保证任何记录集的顺序ORDER BY
,因此以下是如何将 a 添加ROW_NUMBER()
到 XML 结果集:
SELECT i.instance_id,
listitem.x.value('.', 'int') AS item,
ROW_NUMBER() OVER (
PARTITION BY i.instance_id
ORDER BY listitem.x) AS item_order
FROM dbo.instances AS i WITH (NOLOCK)
CROSS APPLY i.list.nodes('/list/item') AS listitem(x);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1130 次 |
最近记录: |