Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 联接是否比直接在表中存储简单值更快?_Sql Server - Fatal编程技术网

Sql server 联接是否比直接在表中存储简单值更快?

Sql server 联接是否比直接在表中存储简单值更快?,sql-server,Sql Server,我们正在构建一个SQL Server数据库,其中包含具有文件类型的行。在90%的案例中,这些类型将是pdf,在10%的案例中是zip。在设计此数据库时,我的第一个想法是对另一个包含类型的表使用外键,如下所示: 档案 文件类型 Id | Name ---+------ 1 'pdf' 2 'zip' 这种设计的一个优点是它使文件表不那么杂乱,理论上它应该占用更少的空间。但是,这种设计还要求我每次要从文件表中选择一行时,都要在文件类型表上执行联接 然后,另一种选择是将文件类型直接存储在

我们正在构建一个SQL Server数据库,其中包含具有文件类型的行。在90%的案例中,这些类型将是
pdf
,在10%的案例中是
zip
。在设计此数据库时,我的第一个想法是对另一个包含类型的表使用外键,如下所示:

档案

文件类型

Id | Name
---+------
1    'pdf'
2    'zip'
这种设计的一个优点是它使文件表不那么杂乱,理论上它应该占用更少的空间。但是,这种设计还要求我每次要从
文件
表中选择一行时,都要在
文件类型
表上执行联接

然后,另一种选择是将
文件类型
直接存储在
文件
表中:

Id | Name    | FileTypeId
---+---------+-----------
1    'f123'     'pdf'
什么样的设计最好?什么更快?哪个更节省空间?

最佳设计完全取决于您的特定需求和使用情况。当然,第一个版本是规范化的,并且是您大多数时候想要的。
Files
表仅维护一个轻量级的
FileTypeId
外键值,可用于在
FileTypes
表中查找。但是,将这两个表合并在一起需要一个联接

在极少数情况下,您可能会发现以下连接查询花费的时间太长:

SELECT f.Id, f.Name, ft.Name AS FileTypeId
FROM Files f
INNER JOIN FileTypes ft
    ON ft.Id = f.FileTypeId;

通常,您的第一道防线是对一个/两个表进行索引。但是,如果索引速度仍然不够快,您可能会在问题中使用非规范化的第二个版本。在这种情况下,您可能会浪费大量存储空间,但作为回报,上面的连接查询将针对单个表,并且可能更快。

我们在这里讨论的是字节差异,但是varchar(3)的文件类型比int小,当然tinyint比两者都小

而且由于文件类型没有固有的顺序(例如,在任何实际意义上,文件类型_id 1实际上并不比文件类型_id 2小),因此使用数字存储文件类型没有绝对的好处

就我个人而言,我会发现一个新的选项(选项3)更容易——为文件类型提供一个有意义的键

Id | Name    | FileTypeId
1    'f123'   'pdf'

FileTypes
Id
'pdf'
'zip'
然后,当查看数据时,它是干净的(您不需要使用视图等进行查找)。但您也可以强制执行引用完整性

编辑:作为清洁度的一个例子,您可能需要进行PDF处理(例如,从PDF中删除标识信息)。在代码中,您可以使用这两个选项中的一个

IF FileType_ID = 14   -- PDFs
   BEGIN
   ... 
   END

IF FileType_ID = 'pdf'
   BEGIN
   ...
   END

警告(作为编辑添加-我将其作为OP回复的现已删除的评论(抱歉))

这有一个(潜在的严重)限制-有意义的键必须表示您希望它的意思

在本例中,如果扩展未定义文件类型,但仍要区分它们,则会遇到问题。例如,您可能有一个“cs”文件类型,它可以是C代码文件,也可以是反打击流视频


在这种情况下,您可能希望将它们分为两种文件类型,然后使用数字表示它们可能是最简单/最有效的方法。

正确设计数据库,使用正确的标准化表,让数据库引擎考虑性能,直到您真的遇到性能问题。我同意上面的评论。这是过早的优化。针对健壮性、可测试性、可维护性、适应性等进行设计。通常,针对这些边缘情况的性能场景只会产生非常小的改进,并且只会产生只代表少数运行时的代码路径。在您确定需要优化的关键路径之前,您是在浪费时间,而这些时间本可以更好地花在其他任何事情上。我明白了。在这种情况下,我们可以预期数据库在Filetable中包含大约100万行,我们应该尽量限制使用的存储空间,因此我们将使用第一个选项。插入如何?假设一个客户端想要插入一个pdf文件。然后我们的API必须首先查询FileTypes表中与“pdf”匹配的行,然后选择其id?嗯,我没有想到这一点。是的,这更有意义。老实说,我真的不在乎身份证。这对我们来说不是问题。
IF FileType_ID = 14   -- PDFs
   BEGIN
   ... 
   END

IF FileType_ID = 'pdf'
   BEGIN
   ...
   END