SQLAlchemy - 每个请求都访问数据库?
我现在在做一个用Python写的网页应用(用的是SQLAlchemy)。为了处理用户登录,应用首先会检查会话里有没有用户ID,如果有,就从数据库里把这个用户的所有信息取出来,并在这次请求中保存下来。然后还会再查询一次,检查这个用户的权限。
我对网页应用开发还比较陌生,但我觉得每次请求都去数据库查这些信息效率不高。这样做算正常吗?
我目前想到的办法是只取一次这些数据,然后保存一些重要的信息(因为大部分数据在每次请求时其实并不需要)。不过,这样就会出现一个问题:如果在这段时间内这个用户的信息被删掉了,那该怎么办呢?有没有好的管理方法?
4 个回答
你说的其实是在讨论如何通过缓存数据来提高性能。一般来说,过早地进行优化是不明智的。因为在你还不知道瓶颈在哪里的时候,优化可能会让事情变得更复杂,尤其是当你对这个应用领域还不熟悉的时候。如果你优化了错误的地方,不仅浪费了时间和精力,还可能让真正需要优化的地方变得更难处理。
请求用户数据通常是个很简单的操作。你可以自己做个简单的测试,看看这会带来多少额外的负担。如果这个负担在你时间预算里并不算多,那就不必去动它。
如果你还是想在应用服务器上缓存数据,那你就得想个办法来处理缓存失效的问题。
一种可能的方案是检查数据库里的变化。如果你要缓存的数据不多,这种方法其实并没有比重新加载数据更有效。
另一种选择是给缓存的数据设置一个过期时间。如果你不需要立即看到变化,这个方法是个不错的选择。
还有一种选择是当数据发生变化时主动使缓存失效。这种方法的可行性取决于你是否只通过应用来修改数据库,以及你是使用单一的应用服务器还是集群解决方案。
在一个简单的网页应用中,用户登录和基本权限的令牌我肯定会存储在基于cookie的会话里。确实,每次请求执行几次SELECT查询并不算什么大问题,但如果你能让一些或全部的网页请求从缓存的数据中获取,而完全不去数据库查询,那就能让这个应用在面对大量用户时更加稳定和高效。
关于用户令牌在数据库中被更改的问题,有两种处理方式。一种是忽略这个问题——对于很多情况来说,用户重新登录以获取新权限并不是大问题(就像Unix系统的例子)。另一种是所有用户信息的修改都会通过一个方法来处理,这个方法也会重置基于cookie的会话状态,但这只有在用户自己通过浏览器进行更改时才有效。
如果以上两种情况都不适用你的情况,那你可能需要在每个请求中都进行一些数据库访问。
“每次请求都去数据库查东西,这样做效率不高。”
这不对。而且,你假设没有缓存,这也是错的。
大多数ORM(对象关系映射)层是可以缓存数据行的,这样可以减少一些数据库查询。
大多数关系型数据库管理系统(RDBMS)都有很强的缓存功能,这样对常见查询的响应速度非常快。
所有的ORM层都会使用一致的SQL,这样也能帮助数据库优化重复的操作。(具体来说,SQL语句会被缓存,这样就能节省解析和计划的时间。)
“这样做算正常吗?”
算。
在你能证明你的查询是应用中最慢的部分之前,不用担心。先构建一个能正常工作的东西。然后再优化那些你能证明是瓶颈的部分。