SQL-如何标记数据?

SQL-如何标记数据?,sql,database,performance,schema,Sql,Database,Performance,Schema,我需要将短标记(A01、B34等)存储在SQL表中,并确保它们被索引。不可能为字母表中的每个字母创建INT列,因为条目可以有多个“A”标记 首先,我将它们存储为一个长字符串,用空格分隔(例如“A01 B34”)。但这需要一个类似于%的查询,它执行完整表扫描并忽略任何索引。所以我在寻找替代品 我现在使用SQLite FTS(文本搜索)来搜索这些标记,但这需要一个特殊的表来存储标记,并使用连接查询获取结果,以及我希望避免的所有其他内容 我的要求非常简单:我需要存储数百万个短字符串,每个字符串都有自己

我需要将短标记(A01、B34等)存储在SQL表中,并确保它们被索引。不可能为字母表中的每个字母创建INT列,因为条目可以有多个“A”标记

首先,我将它们存储为一个长字符串,用空格分隔(例如“A01 B34”)。但这需要一个类似于%的查询,它执行完整表扫描并忽略任何索引。所以我在寻找替代品

我现在使用SQLite FTS(文本搜索)来搜索这些标记,但这需要一个特殊的表来存储标记,并使用连接查询获取结果,以及我希望避免的所有其他内容

我的要求非常简单:我需要存储数百万个短字符串,每个字符串都有自己的标记,并对这些标记进行简单搜索


我目前的方法(对标签进行FTS)是最快的吗?还是使用NoSQL数据库处理此类数据更好?

您没有给我们提供很多详细信息,但您的设计似乎完全错了。它不是第三种正常形式。

@Joshua,请注意术语“正常化”。目前,您的数据已非规范化。非规范化是可能的事情。但在正常化之后,作为某种性能黑客。目前你的设计似乎是错误的

例如,您应该有表1和表3的插图:

some_records (id, column1, ..., columnN)
tags (id, title)
some_records_tags (some_record_id, tag_id)

这是DBMS中的一种经典设计模式。这里不需要NoSQL。

正如其他用户所指出的,数据没有很好地规范化。我假设这是有意为之,并且存在一些非常大的需求(100 gb或tb大小的需求,或者您没有提到的巨大吞吐量需求)。但是,在开始任何路径之前,您应该确切地了解您的需求是什么:写入与读取的频率,写入和读取的延迟要求是什么,并且您必须在计算中包括索引维护

如果您有一个重要的性能需求,您可以尝试在当前的基础上构建一个近线索引系统。我过去曾在大吞吐量需求系统中使用过这种技术。基本上,对于写操作,您可以使它们尽可能小和快,并创建一个批处理过程来返回并将数据添加到二级搜索表中,该二级搜索表将使其成为能够被搜索的表单。这样做的好处是写操作可以很快完成,而且如果选择好聚集索引,则批处理的读取操作可以非常高效地完成。此外,您可以根据需要将数据分段到不同的服务器,以支持更高的搜索吞吐量。主要缺点是更新不会立即反映在搜索结果中

如果您在如下表格中写入: 表数据(id二进制(6),…,时间戳日期时间,标签varchar(256))

并有一个辅助表: 表搜索(标记字符(3),数据标识二进制(6))

您可以创建一个批处理过程,以获取最后一批大小(可能为1000)的记录,并在空格上拆分标记列,并在搜索表中插入/删除标记。在某个地方保留一个变量/行,其中包含从中收集的最后一个时间戳值,并在下一个批处理间隔从那里开始。最后,如果删除很重要,则每个批处理间隔将需要查找数据表中不再存在的记录集。或者,如果您的数据表太大,您可以选择一个逻辑删除表;或者,如果数据删除的频率不够高,您可以同时对数据执行删除和搜索


使用批处理时要注意的是,会使批大小过大,并在更新搜索表时使用表锁。此外,您还必须注意重复的时间戳。当然,在编写/更新数据表时,必须始终更新时间戳。

我将在以前的启动Pageflakes社区网站上分享我的经验。在Pageflakes,用户创建的内容被标记。您可以从这里看到一个示例:

pagecast中的每个小部件都有一组标记。当有人搜索时,我们给标签最高优先级,然后是标题,然后是项目描述

假设您有如下内容表:

Content (id, title, description)
首先,您需要为所有唯一的标记创建一个表

Tag (id, name (unique), countOfItems)
然后需要将标记映射到内容行

TagContentMap (tagid, contentid)
现在您将要求,对于每个新内容,我必须插入三个表中。不总是这样。只有在有新标记时,才能在标记表中插入。大多数时候,人们选择现有的标签。经过几个月的标记,用户应该已经用尽了唯一的标记。从那时起,99%的时间用户选择一些现有的标签。因此,这将为您删除一个插入。因此,您只有一个额外的插入

此外,insert始终显著低于select。最有可能的是,你将有99%的读,1%的写

除非您引入这两个表,否则您永远不会有一个用户界面,用户可以单击一个标记并查看使用该特定标记标记的所有内容。如果您不需要这样的特性,那么您当然可以在内容表本身上添加一个“tags”列,并以逗号分隔的格式存储标记

现在最重要的一点-如何产生最好的搜索结果。在内容表上,我们有一个名为“SearchData”的varchar字段。此字段首先填充标记名,然后填充标题,然后填充说明。所以

SearchData = tag names comma delimited + newline + title + newline + description.
然后使用SQL Server的全文索引仅对SearchData列进行索引,而不对内容表中的任何其他字段进行索引


这对你有用吗?

标签代表什么?也许这将有助于我们将问题形象化。FTS在这方面似乎有点过头了。它们代表了类别。以IMDB为例,每部电影都有多种类型。我知道标准化,你是对的,这种单表设计不是按书设计的。但是我必须存储/搜索大量的数据,即使是每次优化