CQRS 和主键:是否 guid?
对于我的项目(可能是一个大型网站),我选择将命令界面与查询界面分开。因此,提交命令是一种不返回结果的单向操作。这意味着客户端必须提供密钥,例如:
service.SubmitCommand(new AddUserCommand() { UserId = key, ... });
显然我不能使用 int 作为主键,因此 Guid 是一个合乎逻辑的选择 - 除了我到处都读到了它对性能的影响,这让我感到害怕:)
但后来我还了解了 COMB Guid,以及它们如何提供 Guid 的优点,同时仍然具有良好的性能。我还在这里找到了一个实现:Sequential GUID in Linq-to-Sql? 。
因此,在我做出这个重要决定之前:是否有人有这方面的经验或建议?
多谢!
路德
For my project, which is a potentially big web site, I have chosen to separate the command interface from the query interface. As a result, submitting commands are one-way operations that don't return a result. This means that the client has to provide the key, for example:
service.SubmitCommand(new AddUserCommand() { UserId = key, ... });
Obviously I can't use an int for the primary key, so a Guid is a logical choice - except that I read everywhere about the performance impact it has, which scares me :)
But then I also read about COMB Guids, and how they provide the advantages of Guid's while still having a good performance. I also found an implementation here: Sequential GUID in Linq-to-Sql?.
So before I take this important decision: does someone have experience with this matter, of advice?
Thanks a lot!
Lud
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,我使用顺序 GUID 作为主键,并且在性能方面没有任何问题。
大多数测试
顺序 GUID 与 INT 作为主键
都使用批量插入操作并从空闲数据库中选择数据。但在现实生活中,选择和更新是同时发生的。当您应用 CQRS 时,您将不会进行批量插入,并且打开和关闭事务的负担将比 1 个写入查询花费更多的时间。由于您具有独立的读取存储,因此您对具有 GUID PK 的表的选择操作将比在统一存储中具有 INT PK 的表上快得多。
此外,异步为您提供消息传递,使您的应用程序比具有阻塞 RPC 调用的系统更好地扩展。
考虑到上述情况,在我看来,选择 GUID 与 INT 是明智之举,愚蠢之举。
First of all, I use sequential GUIDs as a primary key and I don't have any problems with performance.
Most of tests
Sequential GUID vs INT as primary key
operates with batch insert and selects data from idle database. But in a real life selects and updates happen in SAME time.As you are applying CQRS, you will not have batch inserts and burden for opening and closing transactions will take much more time than 1 write query. As you have separated read storage, your select operations on a table with GUID PK will be much faster than they would be on a table with INT PK in a unified storage.
Besides, asynchrony, that gives you messaging, allows your applications scale much better than systems with blocking RPC calls can do.
In consideration of aforesaid, choosing
GUIDs vs INTs
seems to me as be penny-wise and pound-foolish.您没有指定您正在使用哪个数据库引擎,但既然您提到了 LINQ to SQL,我猜它是 MS SQL Server。
如果是,那么 Kimberly Tripp 对此有一些建议:
用几句话总结这两个链接:
You didn't specify which database engine you are using, but since you mentioned LINQ to SQL, I guess it's MS SQL Server.
If yes, then Kimberly Tripp has some advice about that:
To summarize the two links in a few words:
您可能已经拥有一个像用户名这样的自然键,用于唯一地标识用户,而不是向命令提供 Guid(这对于域来说可能毫无意义)。这个自然键对于用户命令来说更有意义:
如果正确索引用户名列,则可能不需要 GUID。验证这一点的最佳方法是运行测试 - 插入一百万条用户记录并查看 CreateUser 和 Login 的执行情况。如果您确实看到严重的性能影响并且您已经证实会对业务产生不利影响并且无法通过缓存解决,那么然后添加一个 Guid。
如果您正在执行 DDD,您将需要重点关注保持域的整洁,以便代码易于理解并反映实际的业务流程。引入人工密钥与该目标背道而驰,但如果您确定它能为业务提供实际价值,那就继续吧。
Instead of supplying a Guid to a command (which is probably meaningless to the domain), you probably already have a natural key like username which serves to uniquely identify the user. This natural key make a lot more sense for the user commands:
If you index the username column properly, you may not need the GUID. The best way to verify this is to run a test - insert a million user records and see how CreateUser and Login perform. If you really to see a serious performance hit that you have verified adversely affects the business and can't be solved by caching, then add a Guid.
If you're doing DDD, you'll want to focus hard on keeping the domain clean so the code is easy to understand and reflects the actual business processes. Introducing an artificial key is contrary to that goal, but if you're sure that it provides actual value to the business, then go ahead.