Flickr的Cal Henderson 为DjangoCon 2008做了主题演讲.他简要介绍了Django框架在查询中使用表连接,声称"当你达到一定规模时你不使用连接".我希望亨德森知道这些东西,但是有谁知道他的主张可能的推理是什么?
当我说他们是邪恶时,我有点夸张.
对于非常大的数据集,即使它们适合单个数据库,加入也是一项昂贵的操作(许多非顺序IO).通过典型的Web应用程序加载(90/10读/写),您的读取需要尽可能便宜,而您可以在写入上花费更多时间(在许多情况下可以懒惰地复制写入).在典型的高性能Web应用程序中,您将需要在几百毫秒内执行所有数据库IO,这是您的第一个限制.其次,您希望能够执行大量并发请求.这往往指向能够直接从大型表的索引收集记录.有人已经提到你不需要向浏览器发送大量数据,因此不需要在整个数据集中执行连接,但考虑排序:如果你不能直接从正确的顺序获取记录index,在订购结果之前,您需要执行整个连接.
对于多机分区数据,同样的问题适用但规模较大.通常的解决方案是物化视图(数据展平),通过在插入/更新/删除时(或后续延迟)执行多次写入并使用非常简单的索引选择来启用类似连接的查询.
显然,连接很有用,并且在大多数情况下都非常好.但对于本机不支持实体化视图的数据库中的大型数据集,这大大降低了大型数据集的高并发性.
关于Django的具体抱怨是,由于改变现有数据模型的不灵活性,我们鼓励人们创建一对一的映射表,这些映射表只能加入,而不是向现有表添加列.
所有大型可扩展系统都必须不加入.原因在于高分布式数据库,例如Google使用的BigTable,数据非常庞大,超出了一台机器.加入两个GB大小的表格无法以任何方式扩展.事实上,如果你进行大量的连接,你会看到大约500万行,你的RDBMS将开始笨重地依赖索引.好的索引在分布式数据库和mongodb,couchdb等文档数据库中也要困难得多.
未来是一个很好的架构模型作为基础,然后是插入更新队列的数据副本,以便生成扁平化的连接表,并在每组行更改时进行更新.MSSQL,Oracle等中的大型RDBMS都可以满足数据仓库和数据扁平化需求,以便报告速度和Web等高可扩展性需求.
当我们得到Terabytes数据时,Join将成为过去.
我认为这是一个粗略的概括.包含连接的关系数据库概念是现代应用程序员可用的一些最有用和最有价值的工具.
对于大规模数据集而言,非规范化等概念具有其优点.如今,我们倾向于将大型Web应用程序开发人员(视频Facebook,MySpace等)视为福音,而不考虑上下文.
使用索引和外键的优化连接将是正常的,除非你超过300-4亿行标记(我不能说更大,因为这是我们开始在最大的应用程序上存档的限制我现在工作).
我倾向于不同意,因为如果你很好地设计你的数据库,你就可以获得性能.我们有一个使用Kimball星型模型建模的数TB数据仓库,您必须将事实加入维度以进行任何类型的分析并执行(因为它已分区并编入索引).但是我必须在一个进程中生成200m行的摘要输出.这种数量的信息根本不会被用户推送.
但是,对于典型的面向客户端的Web应用程序,每个页面生成返回有限数量的数据,您加入了多少?相反,您的应用程序服务器可以请求行,然后请求相关的行等.当在C语言编程的64K小型8086手持设备上没有关系数据库时,我们有一个ISAM库,我们不得不寻找和读取一个表,然后在另一个表中寻找和阅读.如果你不处理大量数据,那么就像你那样自己做这项工作一样容易.
但它更多的编程和更多的代码意味着更多的错误.它还意味着相当弱的数据库安全性和约束/关系完整性模型.如果没有JOIN,您将更多地访问数据库.在最好的情况下,您将从数据库服务器向Web服务器返回相同数量的信息.如果Web服务器期望针对它检索到的先前行过滤行,则可能会变得更糟.实际上,Web服务器仍在进行JOIN,但当然,扩展Web服务器并且在关系引擎优化方面需要的专业知识更少.