所以我一直在构建django应用程序一段时间,并且使用了cool-aid和all:只使用ORM并且从不编写自定义SQL。
当您拥有大量用户特定内容(即照片,朋友,其他数据等)时,网站的主页面(用户将花费80%的主要界面 - 90%的时间)变慢
所以我弹出了sql logger(预先安装了pinax,我只是在设置中启用了它)并想象我报告超过 500个数据库查询时的惊喜 !!使用手动编码的sql,我在最复杂的页面上几乎没有超过50个。
事后看来,这并不是一件令人惊讶的事情,但似乎这并不好。
...即使只有十几个查询需要1ms +
所以我想知道,往返于mysql 的开销是多少? django和mysql正在相同的服务器上运行,因此不应该有任何与网络相关的开销。
答案 0 :(得分:4)
仅仅因为您使用ORM并不意味着您不应该进行性能调整。
我 - 像你一样 - 是我的一个性能低下的应用程序的主页。我看到我正在做数百个查询来显示该页面。我去查看我的代码,并意识到通过谨慎使用select_related()
我的查询会带来更多我需要的数据 - 我从数百个查询变为数十个。
您还可以运行SQL事件探查器,看看是否有索引可以帮助您最常见的查询 - 您知道,标准数据库的东西。
缓存也是你的朋友,我想。如果很多页面没有改变,你是否需要每次都查询数据库?
如果一切都失败了,请记住:ORM很棒,是的 - 你应该尝试使用它,因为它是Django哲学; 但你没有和它结婚。
如果您确实有一个用于学习和调优ORM导航没有帮助的用例,如果您确定使用标准查询可以做得更好:在这种情况下使用原始SQL。
答案 1 :(得分:3)
每个查询的开销只是图片的一部分。 Django和Mysql服务器之间的实际往返时间可能非常小,因为大多数查询都会在不到一毫秒的时间内回来。更大的问题是发给数据库的查询数量很快就会超过它。对一个页面的500个查询是很多的,甚至50对我来说似乎很多。如果十个用户查看复杂页面,那么现在最多可以查询5000个。
当呼叫者从广域网访问数据库时,数据库服务器的往返时间更是一个因素,其中往返可以很容易地在20ms到100ms之间。
我肯定会考虑使用某种缓存。
答案 2 :(得分:2)
有一些方法可以减少查询量。
使用.filter()
和.all()
获取大量内容;在视图功能中选择(或通过{%if%}
模板)。 Python可以比MySQL更快地处理一批行。
“但我可以向模板发送太多内容”。没错,但是你会执行更少的SQL请求。测量哪个更好。
这是您在编写SQL时常用的操作。这没有错 - 它不会破坏ORM - 但它会优化底层数据库工作并将处理放入视图函数和模板中。
避免在模板中进行查询导航。执行{{foo.bar.baz.quux}}时,SQL用于获取与bar
相关联的foo
,然后使用与baz
相关联的bar
,然后quux
与baz
相关联。您可以通过一些谨慎的.filter()
和Python处理来减少此查询业务,以在视图函数中组合有用的元组。
同样,这是您在手工制作SQL时常常要做的事情。在这种情况下,您在视图函数中收集较大批量的ORM管理对象,并使用Python进行过滤,而不是通过大量单独的ORM请求进行过滤。
这不会破坏ORM。它将使用情况从大量小查询更改为一些较大的查询。
答案 3 :(得分:1)
数据库调用总是有开销,在这种情况下,开销不是 错误,因为应用程序和数据库在同一台机器上,因此没有网络延迟,但仍然有很大的成本
当您向数据库发出请求时,它必须准备通过执行以下操作来为该请求提供服务,包括:
这只是大多数数据库管理系统处理SQL请求所做事情的概述。即使查询本身运行相对较快,您也会产生500次此开销。即使到本地数据库,底线数据库交互也不像你想象的那么便宜。