具有数百万行的 Django 表
Posted
技术标签:
【中文标题】具有数百万行的 Django 表【英文标题】:Django Table with Million of rows 【发布时间】:2011-01-04 07:42:41 【问题描述】:我有一个包含 2 个应用程序(书籍和阅读器)的项目。
Books 应用程序有一个包含 400 万行的表,其中包含以下字段:
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 万行的表是一个很好的解决方案吗?
有其他解决方案吗?
谢谢^__^
【问题讨论】:
400 万不是很多,你有过早优化的情况。 使用自动完成字段从 ajax 查询该表,views.py 中有此查询:books.objects.filter(book_title__istartswith=request.GET['q'])[:100]跨度> 如果您在文本字段上查询表格并且性能是问题,您可以选择实现全文搜索。但是,您查询的字段的大小仅为 40 个字符,我不确定它是否对数据库造成了大问题。 这不是您提出的问题,但您可能会发现这很有帮助:***.com/questions/1566717/… 【参考方案1】:正如许多人所说,将表拆分为更小的表(水平分区甚至分片)还为时过早。数据库用于处理这种大小的表,因此您的性能问题可能出在其他地方。
索引是第一步,不过听起来你已经完成了。数据库应该可以处理 400 万行索引。
其次,检查您正在运行的查询数量。您可以使用 django 调试工具栏之类的工具来执行此操作,并且您经常会惊讶于执行了多少不必要的查询。
缓存是下一步,对大多数用户未更改的页面或部分页面使用 memcached。在这里,您只需付出很少的努力,就能获得最大的性能提升。
如果你真的,真的需要拆分表,最新版本的 django (1.2 alpha) 可以处理分片(例如多数据库),你应该能够手写一个水平分区解决方案(postgres 提供in-db 方式来做到这一点)。请不要使用流派来拆分表格!选择您永远不会改变的东西,并且在进行查询时您将永远知道。像作者一样,除以姓氏的第一个字母或其他东西。对于一个不是特别大的数据库来说,这是一个很大的努力并且有许多缺点——这就是为什么这里的大多数人都反对它!
[编辑]
我忽略了非规范化!将常见的计数、总和等放在例如作者表中,以防止常见查询的连接。缺点是您必须自己维护它(直到 django 添加了 DenormalizedField)。我会在开发过程中查看清楚、直接的案例或在缓存失败后查看此内容 --- 但好吧在分片或水平分区之前。
【讨论】:
好的,如果我要拆分表,我将按第一个字母拆分...确实更合理:) 使用views.py 中的此查询的自动完成字段从ajax 查询表: books.objects.filter(book_title__istartswith=request.GET['q'])[:100] 那么你推荐我 index + memcached 吗?谢谢 在标题的前三个字母(或者你开始查询数据库的第一个数字)上建立一个索引,它会运行得很快。【参考方案2】:ForeignKey
在数据库中以IntegerField
的形式实现,因此以削弱模型为代价的成本几乎为零。
编辑: 并且看在皮特的份上,将其保存在一个表中并酌情使用索引。
【讨论】:
我正在使用索引,但该表有 400 万行并且经常被查询。所以不知道索引够不够:-\ 如果不是,那么数据库需要更多内存。 400 万行是不容小觑的,但是数据库是为这种事情而构建的,尤其是在您进行索引时。只有当您的行数达到至少一亿行时,我才会担心。【参考方案3】:我对 Django 不熟悉,但是对 DB 有一个大概的了解。
当您拥有大型数据库时,index your database 很正常。这样一来,检索数据应该很快。
在将书籍与阅读器关联时,您应该创建另一个表,将阅读器链接到书籍。
将书籍按主题划分并不是一个坏主意。但我不确定你说的有 20 个应用程序是什么意思。
【讨论】:
20 个应用程序意味着 20 个表 :) 我正在使用索引,但该表有 400 万行并且经常被查询。所以不知道索引够不够:-\ 天哪!不要把它分成20张桌子!为您的表制作一个 EAR 图,您将看到您需要处理这个额外的表。例如。用于将人与书籍、类别与书籍等相关联的额外表格。【参考方案4】:您有性能问题吗?如果是这样,您可能需要add a few indexes。
了解索引的帮助的一种方法是查看数据库服务器的查询日志(instructions here,如果您使用的是 mysql)。
如果您没有遇到性能问题,那就继续吧。数据库可以处理数百万条记录,而 django 非常擅长生成合理的查询。
【讨论】:
是的,这是一个性能问题。我正在使用索引,但该表有 400 万行并且经常被查询。所以不知道索引够不够:-\ 更大的索引(更多列)可能是要走的路,也许除了@jcm提到的memcached。单列索引通常没有帮助,因为它们没有被您的查询使用。【参考方案5】:解决此类问题的常用方法是Sharding。不幸的是,实现它主要取决于 ORM(Hibernate 做得很好),而 Django 不支持这一点。但是,我不确定 400 万行是否真的那么糟糕。您的查询应该仍然是完全可管理的。
也许您应该考虑使用memcached 之类的缓存。 Django supports this 挺好的。
【讨论】:
【参考方案6】:您还没有提到您使用的是哪个数据库。一些数据库(如 MySQL 和 PostgreSQL)具有非常保守的开箱即用设置,除了小型服务器上的小型数据库之外,这些设置基本上无法用于任何东西。
如果您告诉我们您正在使用哪个数据库,它在什么硬件上运行,以及该硬件是否与其他应用程序共享(例如,它是否也为 Web 应用程序提供服务),那么我们或许可以为您提供一些具体的调优建议。
例如,对于 MySQL,您可能需要调整 InnoDB 设置;对于 PostgreSQL,您需要更改 shared_buffers 和许多其他设置。
【讨论】:
以上是关于具有数百万行的 Django 表的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 pandas 或 python 将具有数百万行的表从 PostgreSQL 复制到 Amazon Redshift
当 SQL Server 表中的列“createdDate”从现在起经过 90 天后,如何更新其具有数百万行的列?我们可以使用触发器吗?