我有2个应用程序(书籍和读者)的项目。
Books应用程序有一个表,表中有4百万行,其中包含以下字段:
book_title = models.CharField(max_length=40)
book_description = models.CharField(max_length=400)
为了避免查询具有400万行的数据库,我正在考虑按主题划分(20个模型,20个表,200.000行(book_恐怖,book_drammatic,ecc))。
在“reader”应用程序中,我想插入以下字段:
reader_name = models.CharField(max_length=20, blank=True)
book_subject = models.IntegerField()
book_id = models.IntegerField()
因此,我考虑使用整数“book_subject”(允许访问适当的表)和“book_id”(允许访问“book_subject”中指定的表中的图书),而不是ForeignKey。
是避免查询具有4百万行的表的好解决方案吗?
是否有替代解决方案?
7条答案
按热度按时间rm5edbpk1#
正如许多人所说,将表拆分为更小的表(水平分区甚至分片)还为时过早,数据库就是用来处理这种大小的表的,所以性能问题可能出在其他地方。
索引是第一步,听起来你已经做了。400万行数据库应该可以用索引来处理。
第二,检查你正在运行的查询的数量,你可以用django调试工具栏来完成,你会经常惊讶于有多少不必要的查询正在被执行。
缓存是下一步,对大多数用户来说没有改变的页面或页面的一部分使用memcached,这是你用很少的努力就能看到最大的性能提升的地方。
如果你真的真的需要拆分表格,最新版本的django(1.2 alpha)可以处理分片(例如多数据库),并且您应该能够手动编写水平分区解决方案(postgres提供了一种in-db的方式来实现).请不要使用genre来分割表格!选择一些你从来没有过的东西,永远不会改变,你在查询的时候总是知道的。比如作者,用姓氏的第一个字母来划分,或者其他什么。这是一个很大的工作量,对于一个不是很大的数据库来说有很多缺点---这就是为什么这里的大多数人都反对它!
[编辑]
我忽略了反规范化!把常见的计数,和等放在例如author表中,以防止在常见的查询上连接。缺点是你必须自己维护它(直到django添加了一个反规范化字段)。我会在开发过程中查看这个,以获得清晰,直接的案例,或者在缓存失败之后---但是在分片或水平分区之前。
iezvtpos2#
ForeignKey
在数据库中被实现为IntegerField
,因此您保存的成本很少,甚至没有任何成本,但代价是削弱您的模型。**编辑:**为了方便起见,请将其保存在一个表中,并根据需要使用索引。
laximzn53#
你还没有提到你使用的是哪个数据库。有些数据库--比如MySQL和PostgreSQL --有非常保守的开箱即用设置,除了小型服务器上的小型数据库外,基本上什么都不能用。
如果您告诉我们您正在使用哪个数据库,它运行在什么硬件上,以及该硬件是否与其他应用程序共享(例如,它是否也为Web应用程序服务),那么我们可能会为您提供一些具体的调整建议。
例如,对于MySQL,您可能需要调优InnoDB设置;对于PostgreSQL,您需要更改shared_buffers和许多其他设置。
ffdz8vbo4#
我不熟悉Django,但我对DB有一个大致的了解。
当你有大型数据库时,index your database是很正常的,这样的话,检索数据应该很快。
当要将一本书与一个阅读器关联起来时,您应该创建另一个表,将阅读器链接到书。
把书按科目分类是个不错的主意。但是我不明白你说有20份申请书是什么意思。
xwbd5t1u5#
您是否遇到性能问题?如果是,您可能需要添加一些索引。
了解索引在哪些方面有帮助的一种方法是查看数据库服务器的查询日志(如果使用MySQL,则为instructions here)。
如果你没有性能问题,那就用它吧,数据库是用来处理数百万条记录的,而django非常擅长生成合理的查询。
62lalag46#
Sharding是解决这类问题的常用方法。不幸的是,它主要由ORM来实现(Hibernate做得很好),而Django不支持这一点。然而,我不确定400万行是否真的那么糟糕。您的查询仍然应该是完全可管理的。
也许你应该看看memcached之类的缓存,Django支持得很好。
368yc8dk7#
你可以使用服务器端的数据表,如果你可以实现一个服务器端的数据表,你将能够在不到一秒钟的时间里拥有超过四百万条记录。