MySql往返的开销?

时间:2009-11-06 17:18:28

标签: python mysql django overhead

所以我一直在构建django应用程序一段时间,并且使用了cool-aid和all:只使用ORM并且从不编写自定义SQL。

当您拥有大量用户特定内容(即照片,朋友,其他数据等)时,网站的主页面(用户将花费80%的主要界面 - 90%的时间)变慢

所以我弹出了sql logger(预先安装了pinax,我只是在设置中启用了它)并想象我报告超过 500个数据库查询时的惊喜 !!使用手动编码的sql,我在最复杂的页面上几乎没有超过50个。

事后看来,这并不是一件令人惊讶的事情,但似乎这并不好。

...即使只有十几个查询需要1ms +

所以我想知道,往返于mysql 的开销是多少? django和mysql正在相同的服务器上运行,因此不应该有任何与网络相关的开销。

4 个答案:

答案 0 :(得分:4)

仅仅因为您使用ORM并不意味着您不应该进行性能调整。

我 - 像你一样 - 是我的一个性能低下的应用程序的主页。我看到我正在做数百个查询来显示该页面。我去查看我的代码,并意识到通过谨慎使用select_related()我的查询会带来更多我需要的数据 - 我从数百个查询变为数十个。

您还可以运行SQL事件探查器,看看是否有索引可以帮助您最常见的查询 - 您知道,标准数据库的东西。

缓存也是你的朋友,我想。如果很多页面没有改变,你是否需要每次都查询数据库?

如果一切都失败了,请记住:ORM很棒,是的 - 你应该尝试使用它,因为它是Django哲学; 但你没有和它结婚

如果您确实有一个用于学习和调优ORM导航没有帮助的用例,如果您确定使用标准查询可以做得更好:在这种情况下使用原始SQL。

答案 1 :(得分:3)

每个查询的开销只是图片的一部分。 Django和Mysql服务器之间的实际往返时间可能非常小,因为大多数查询都会在不到一毫秒的时间内回来。更大的问题是发给数据库的查询数量很快就会超过它。对一个页面的500个查询是很多的,甚至50对我来说似乎很多。如果十个用户查看复杂页面,那么现在最多可以查询5000个。

当呼叫者从广域网访问数据库时,数据库服务器的往返时间更是一个因素,其中往返可以很容易地在20ms到100ms之间。

我肯定会考虑使用某种缓存。

答案 2 :(得分:2)

有一些方法可以减少查询量。

  1. 使用.filter().all()获取大量内容;在视图功能中选择(或通过{%if%}模板)。 Python可以比MySQL更快地处理一批行。

    “但我可以向模板发送太多内容”。没错,但是你会执行更少的SQL请求。测量哪个更好。

    这是您在编写SQL时常用的操作。这没有错 - 它不会破坏ORM - 但它会优化底层数据库工作并将处理放入视图函数和模板中。

  2. 避免在模板中进行查询导航。执行{{foo.bar.baz.quux}}时,SQL用于获取与bar相关联的foo,然后使用与baz相关联的bar,然后quuxbaz相关联。您可以通过一些谨慎的.filter()和Python处理来减少此查询业务,以在视图函数中组合有用的元组。

    同样,这是您在手工制作SQL时常常要做的事情。在这种情况下,您在视图函数中收集较大批量的ORM管理对象,并使用Python进行过滤,而不是通过大量单独的ORM请求进行过滤。

    这不会破坏ORM。它将使用情况从大量小查询更改为一些较大的查询。

答案 3 :(得分:1)

数据库调用总是有开销,在这种情况下,开销不是 错误,因为应用程序和数据库在同一台机器上,因此没有网络延迟,但仍然有很大的成本

当您向数据库发出请求时,它必须准备通过执行以下操作来为该请求提供服务,包括:

  • 将资源(内存缓冲区,临时表等)分配给将处理请求的数据库服务器连接/线程,
  • 反序列化sql和参数(即使在一台机器上也是如此,因为这是一个进程间请求,除非您使用的是嵌入式数据库)。
  • 检查查询缓存中是否存在查询,如果不优化它并将其放入缓存中。
    • 另请注意,如果您的查询未进行参数化(即值未与SQL分离),则可能导致语句的高速缓存未命中,这应该相同,这意味着每个请求都会导致查询被分析和优化时间。
  • 处理查询。
  • 准备并将结果返回给客户。

这只是大多数数据库管理系统处理SQL请求所做事情的概述。即使查询本身运行相对较快,您也会产生500次此开销。即使到本地数据库,底线数据库交互也不像你想象的那么便宜。