代码之家  ›  专栏  ›  技术社区  ›  Bartek

Django(?)在执行了一些Python分析之后,对大型数据集的速度非常慢

  •  5
  • Bartek  · 技术社区  · 15 年前

    我比较了我的一个旧的PHP脚本与更新的、更高级的django版本和php版本,其中完全吐出了HTML,所有脚本的运行速度都更快。快得多,以至于在姜戈一号上出了点问题。

    首先,有一些上下文:我有一个页面,它可以输出销售数据的报告。数据可以通过许多东西进行过滤,但主要是通过日期进行过滤。这使得缓存它有点困难,因为结果的可能性几乎是无穷无尽的。虽然已经完成了大量的数字和计算工作,但在PHP中处理这个问题并不是什么大问题。

    更新:

    • 经过一些额外的测试后,我认为没有任何东西可以导致减速。如果我只是对数据进行数字处理并吐出5行呈现的HTML,那么速度就没有那么慢(仍然比PHP慢),但是如果我呈现大量数据,那么速度就非常慢。

    • 每当我运行一个大报告时(例如,本年度的所有销售),机器的CPU使用率将达到100%。不知道这意味着什么。我使用的是mod_python和apache。也许切换到WSGi会有所帮助?

    • 我的模板标记,显示在0.1秒到1秒之间的任何地方对真正大的集合进行分类汇总/汇总处理。我在报告中给他们打了6次电话,所以他们似乎不是最大的问题。

    现在,我运行了一个Python分析器,并返回了以下结果:

    Ordered by: internal time
       List reduced from 3074 to 20 due to restriction 
    
       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      2939417   26.290    0.000   44.857    0.000 /usr/lib/python2.5/tokenize.py:212(generate_tokens)
      2822655   17.049    0.000   17.049    0.000 {built-in method match}
      1689928   15.418    0.000   23.297    0.000 /usr/lib/python2.5/decimal.py:515(__new__)
     12289605   11.464    0.000   11.464    0.000 {isinstance}
       882618    9.614    0.000   25.518    0.000 /usr/lib/python2.5/decimal.py:1447(_fix)
        17393    8.742    0.001   60.798    0.003 /usr/lib/python2.5/tokenize.py:158(tokenize_loop)
           11    7.886    0.717    7.886    0.717 {method 'accept' of '_socket.socket' objects}
       365577    7.854    0.000   30.233    0.000 /usr/lib/python2.5/decimal.py:954(__add__)
      2922024    7.199    0.000    7.199    0.000 /usr/lib/python2.5/inspect.py:571(tokeneater)
       438750    5.868    0.000   31.033    0.000 /usr/lib/python2.5/decimal.py:1064(__mul__)
        60799    5.666    0.000    9.377    0.000 /usr/lib/python2.5/site-packages/django/db/models/base.py:241(__init__)
        17393    4.734    0.000    4.734    0.000 {method 'query' of '_mysql.connection' objects}
      1124348    4.631    0.000    8.469    0.000 /usr/lib/python2.5/site-packages/django/utils/encoding.py:44(force_unicode)
       219076    4.139    0.000  156.618    0.001 /usr/lib/python2.5/site-packages/django/template/__init__.py:700(_resolve_lookup)
      1074478    3.690    0.000   11.096    0.000 /usr/lib/python2.5/decimal.py:5065(_convert_other)
      2973281    3.424    0.000    3.424    0.000 /usr/lib/python2.5/decimal.py:718(__nonzero__)
       759014    2.962    0.000    3.371    0.000 /usr/lib/python2.5/decimal.py:4675(__init__)
       381756    2.806    0.000  128.447    0.000 /usr/lib/python2.5/site-packages/django/db/models/fields/related.py:231(__get__)
       842130    2.764    0.000    3.557    0.000 /usr/lib/python2.5/decimal.py:3339(_dec_from_triple)
    

    tokenize.py出现在最前面,这可能有一些意义,因为我正在做大量的数字格式化。decimal.py很有意义,因为报告基本上是90%的数字。我不知道内置的方法是什么 match 就像我在自己的代码中没有做任何regex或类似的操作一样(Django正在做什么?)最接近的是我正在使用ITertools iFilter。

    这似乎是主要的罪魁祸首,如果我能找到如何减少处理时间的那些,那么我将有一个更快的页面。

    有人对我如何开始减少这个有什么建议吗?我真的不知道如何解决这个标记化/十进制问题而不简单地删除它们。

    更新:我在大多数数据上运行了一些带有/不带过滤器的测试,结果返回的时间基本相同,后者更快,但不是问题的原因。tokenize.py中到底发生了什么?

    4 回复  |  直到 15 年前
        1
  •  6
  •   Astra    15 年前

    对于您的问题,有很多事情需要假设,因为您没有任何类型的代码示例。

    以下是我的假设:您使用的是Django的内置ORM工具和模型(即sales data=modelobj.objects().all()),在PHP方面,您处理的是直接的SQL查询和查询集。

    Django正在进行大量类型转换和转换,将数据类型从数据库查询转换为ORM/模型对象和关联的管理器(默认情况下为objects())。

    在PHP中,您控制转换并确切知道如何从一种数据类型转换为另一种数据类型,您只需根据该问题节省一些执行时间。

    我建议您尝试将一些花哨的数字工作转移到数据库中,特别是在您正在进行基于记录集的处理时——数据库会从早餐开始接受这种处理。在Django中,可以将原始SQL发送到数据库: http://docs.djangoproject.com/en/dev/topics/db/sql/#topics-db-sql

    我希望这至少能让你找到正确的方向…

        2
  •  2
  •   S.Lott    15 年前

    “tokenize.py出现在最前面,这可能有一些意义,因为我正在进行大量的数字格式设置。”

    完全没有意义。

    http://docs.python.org/library/tokenize.html .

    tokenize模块提供了一个词汇 python源代码扫描器, 在python中实现

    标记化出现在顶部意味着您正在进行动态代码解析。

    Afaik(在Django存储库中进行搜索)Django不使用标记化。这样您的程序就可以进行某种动态代码实例化。或者,你只是在分析 第一 程序加载、分析和运行的时间,导致错误的时间假设。

    你应该 曾经在模板标记中进行过计算——这很慢。它涉及模板标记的复杂元评估。您应该使用简单、低开销的Python在视图中进行所有计算。仅将模板用于演示文稿。

    此外,如果您经常进行查询、筛选、求和等操作,那么您就有了一个数据仓库。获取一本关于数据仓库设计的书,并遵循数据仓库设计模式。

    必须有一个中央事实数据表,由维度表包围。这是非常,非常有效的。

    总和、分组依据等可作为 defaultdict python中的操作。批量获取所有行,生成具有所需结果的字典。如果速度太慢,那么您必须使用数据仓库技术来保存与您的细粒度事实分开的持久的和和组。通常,这涉及到走出django ORM并使用RDBMS特性,如派生数据的视图或表。

        3
  •  2
  •   mikl    15 年前

    在处理大数据集时,还可以使用 ValuesQuerySet 它更直接地访问查询结果,而不是为结果中的每一行创建模型对象实例。

    它的用法看起来有点像这样:

    Blog.objects.order_by('id').values()
    
        4
  •  1
  •   Haes    15 年前

    在这种情况下,数据库往往是瓶颈。此外,使用ORM可能会导致次优的SQL查询。

    正如一些人指出的那样,仅仅凭你提供的信息是不可能说出问题的实质的。

    我可以给你一些一般性的建议:

    • 如果视图正在处理相关的模型对象,请考虑使用 select_related() . 这个简单的方法可以大大加速ORM生成的查询。
    • 使用 Debug Footer Middleware 查看您的视图生成了哪些SQL查询,以及执行这些查询所花费的时间。

    附言:仅供参考,我曾经有一个相当简单的观点,这是非常缓慢的。安装后 调试页脚中间件 我在500左右看到的!SQL查询是在该单一视图中执行的。只是使用 选择“相关”() 将其归结为5个查询,并按预期执行视图。