我们正在设计一个通常是OLTP的应用程序(想想:采购系统)。但是,这个特别需要一些用户离线,因此他们需要能够将数据库下载到他们的机器上,对其进行操作,然后在局域网上进行同步。
我想请注意,我知道之前已经完成了这项工作,我只是没有这个特定模型的经验。
我想到的一个想法是使用GUID作为表键。因此,例如,采购订单不会有数字(自动数字)而是GUID,因此每个离线客户端都可以生成这些数据,当我连接回数据库时,我没有冲突。
出于某种原因这是个坏主意吗? 通过GUID键访问这些表会很慢吗?
您是否有过使用这类系统的经验?你是怎么解决这个问题的?
谢谢!
丹尼尔
答案 0 :(得分:8)
使用Guids作为主键是可以接受的,并且由于您考虑它们的相同原因而被认为是相当标准的做法。它们可能被过度使用,这会使调试和管理变得有些繁琐,所以如果可能的话,尽量让它们远离代码表和其他参考数据。
您必须关注的是人类可读的标识符。 Guids不能被人交换 - 你能想象如果它是一个guid,试图通过电话确认你的订单号吗?因此,在离线方案中,您可能仍需要生成某些内容 - 例如发布者(工作站/用户)ID和一些序列号,因此订单号可能是123-5678 - 。
然而,这可能无法满足具有序号的业务要求。事实上,监管要求可能会受到影响 - 某些法规(SOX可能)要求发票号码是连续的。在这种情况下,可能需要生成一种形式编号,该编号稍后在系统同步时修复。您可能会使用具有OrderId(Guid),OrderNo(int),ProformaOrderNo(varchar)的表格 - 可能会出现一些复杂性。
至少将guid作为主键意味着当最终发生同步时,您不必进行大量的级联更新 - 只需更新人类可读的数字。
答案 1 :(得分:3)
@SqlMenace
GUID存在其他问题,您看到GUID不是顺序的,因此插入将遍布整个地方,这会导致页面拆分和索引碎片
不正确。 主键!=聚集索引。
如果聚集索引是另一列(请注意“inserted_on”),那么插入将是顺序的,不会发生页面拆分或发生过多碎片。
答案 2 :(得分:2)
这是对GUID的完美使用。唯一的缺点是使用GUID比INT更轻微的复杂性和轻微的大小差异(16字节对4字节)。
我认为这些都不是什么大问题。
答案 3 :(得分:1)
将通过访问这些表 GUID键慢吗?
GUID存在其他问题,您看到GUID不是顺序的,因此插入将遍布整个地方,这会导致页面拆分和索引碎片
在SQL Server 2005 MS中引入了NEWSEQUENTIALID()来解决这个问题,唯一的问题可能是你只能使用NEWSEQUENTIALID作为表中的默认值
答案 4 :(得分:1)
你是对的,这是一个老问题,它有两个规范的解决方案:
使用唯一标识符作为主键。请注意,如果您担心可读性,则可以滚动自己的唯一标识符,而不是使用GUID。唯一标识符将使用有关日期和机器的信息来生成唯一值。
使用'Actor'+标识符的复合键。每个用户都获得一个数字actor ID,新插入的行的键使用actor ID以及下一个可用的标识符。因此,如果两个actor都插入ID为“100”的新行,则不会违反主键约束。
就个人而言,我更喜欢第一种方法,因为我认为复合键作为外键非常繁琐。我认为人类可读性投诉被夸大了 - 最终用户不应该对你的密钥有任何了解!
答案 5 :(得分:1)
确保使用guid.comb - 处理索引内容。如果您在此之后处理性能问题,那么您将在短期内成为缩放专家。
使用GUID的另一个原因是启用数据库重构。假设您决定将多态或继承或其他任何内容应用于您的Customers实体。您现在希望客户和员工从Person派生并让他们共享一个表。拥有真正唯一的标识符可简化数据迁移。没有可与之对抗的序列或整数标识字段。
答案 6 :(得分:1)
我只想指出What are the performance improvement of Sequential Guid over standard Guid?,其中涵盖了GUID演讲。
为了人类可读性,请考虑分配机器ID,然后使用这些机器中的序列号作为可能性。但这需要管理机器ID的分配。可以在一列或两列中完成。
我个人非常喜欢SGUID的答案。
答案 7 :(得分:0)
Guids肯定比标准整数键更慢(并且使用更多内存),但这是否是一个问题将取决于您的系统将看到的负载类型。根据您的后端数据库,索引guid字段可能会出现问题。
使用guids可以简化整个类的问题,但是你需要为它付出部分性能和可调试性 - 在这些测试查询中输入guid会变得非常快![/ p>
答案 8 :(得分:0)
后端将是SQL Server 2005
前端/应用逻辑将是.Net
除了GUID之外,你能想到解决离线计算机将新数据同步回中央数据库时发生的“合并”的其他方法吗?
我的意思是,如果键是INT,我必须在导入时重新编号。 GUID将使我免于此。
答案 9 :(得分:0)
当我们必须将两个数据库合并为一个数据库时,使用GUID为我们节省了大量的工作。
答案 10 :(得分:0)
如果您的数据库足够小,可以下载到笔记本电脑并离线使用,那么您可能不必过多担心整数和Guid之间的性能差异。但是,在开发和排除系统故障时,不要低估有用的内容!无论你是否使用Guids,你可能需要提出一些相当复杂的导入/同步逻辑,因此它们可能没有你想象的那么多。
答案 11 :(得分:0)
@Simon,
你提出了非常好的观点。我已经在考虑离线时生成的“临时”“人类可读”数字,我会在同步时重新创建。但我想避免使用外键等等。
答案 12 :(得分:0)
我会开始看看SQL Server Compact Edition!它有助于解决您的所有问题。
Data Storage Architecture with SQL Server 2005 Compact Edition
专为
设计现场部队应用程序(FFA)。游离脂肪酸 通常分享一个或多个 以下属性
他们允许用户执行他们的 断开连接时的作业功能 一个后端网络现场 客户所在地,在路上,在 机场,或从家里。
FFA通常是为 偶尔的连接,意味着 当用户运行客户端时 应用程序,他们不需要 任何类型的网络连接。游离脂肪酸 经常涉及多个客户 可以同时访问和使用数据 来自后端数据库,两者都在 连接和断开模式。
FFA必须能够复制数据 从后端数据库到 客户端数据库用于离线支持 他们还需要能够复制 修改,添加或删除数据 从客户端到服务器的记录 当应用程序能够 连接到网络
答案 13 :(得分:0)
首先想到的是:MS是否设计了DataSet和DataAdapter模型来支持这样的场景?
我相信我读到MS将他们的ADO记录集模型更改为当前的DataSet模型,因此它也可以脱机工作。还有这个Sync Services for ADO.NET
我相信我已经看到了使用DataSet模型的代码,该模型也使用外键,并且在使用DataAdapter时它们仍能完美同步。虽然我没有尝试过同步服务,但我认为你也可以从中受益。
希望这有帮助。
答案 14 :(得分:0)
@Portman默认情况下,PK == Clustered Index,创建主键约束会自动创建聚簇索引,如果不希望聚类,则需要指定非聚簇索引。