我有一个包含2个应用程序的项目(书籍和阅读器)。
图书应用程序有一个表,该表包含4百万行,其中包含以下字段:
book_title = models.CharField(max_length=40)
book_description = models.CharField(max_length=400)
为了避免用400万行查询数据库,我正在考虑按主题对数据库进行划分(20个模型,其中20个表具有200.000行(book_horror,book_drammatic,ecc)。
在“阅读器”应用程序中,我正在考虑插入以下字段:
reader_name = models.CharField(max_length=20, blank=True)
book_subject = models.IntegerField()
book_id = models.IntegerField()
因此,我考虑使用整数“book_subject”(允许访问适当的表)和“book_id”(允许访问“book_subject”中指定的表中的书)来代替ForeignKey。
一个好的解决方案是避免查询具有四百万行的表?
有替代解决方案吗?
谢谢^ __ ^
最佳答案
就像许多人所说的,将表拆分成较小的表(水平分区甚至分片)还为时过早。数据库是用来处理这种大小的表的,因此您的性能问题可能在其他地方。
索引是第一步,但听起来您已经这样做了。数据库应可以使用索引处理400万行。
其次,检查您正在运行的查询数。您可以使用django调试工具栏之类的工具来执行此操作,并且您经常会惊讶地发现正在进行许多不必要的查询。
缓存是下一步,对大多数用户未使用的页面或部分页面使用memcached。在这里,您只需花费很少的精力即可看到最大的性能提升。
如果确实需要拆分表,则最新版本的django(1.2 alpha)可以处理分片(例如,多数据库),并且您应该可以手写水平分割解决方案(postgres提供了一个in-db方法)。请不要使用流派来拆分表格!选择您永远不会改变的东西,并且在查询时会永远知道。像作者一样,用姓氏或首字母除以。对于不是特别大的数据库,这需要很多工作,并且存在许多缺点---这就是为什么这里的大多数人都建议不要这样做!
[编辑]
我省去了非规范化!将常见的计数,总和等放入“作者”表中,以防止对常见查询进行联接。缺点是您必须自己维护它(直到django添加DeNormalizedField为止)。在开发过程中,我会考虑清楚,直接的情况,或者在缓存使您失败之后查看它,但是要在分片或水平分区之前。