我想优化一下性能,但是有一个地方有 2 种写法,我不知道哪种好一点,就是比如有条数据进来,我要先判断这条数据在不在,如果在就更新,不在就直接新建一条
伪代码如下:
方法 1 )
try: article = Article.objects.get(id=9999) 触发:更新逻辑 except: 触发:新建逻辑
方法 2 )
article = Article.objects.filter(id=9999) if article.exists(): exist_article = article[0] 触发:更新逻辑 else: 触发:新建逻辑
感觉方法 1 有点奇怪,但是似乎就访问一次数据库,方法二嗦一点,不知道有没有老鸟能提供帮助?
![]() | 1 wuwukai007 2021-01-26 19:50:13 +08:00 get_or_create |
2 youngce 2021-01-26 19:51:38 +08:00 Article.objects.update_or_create() ? |
3 Phishion OP @wuwukai007 请问,这种分装好的底层又是怎么实现的呢? |
4 renmu123 2021-01-26 19:51:58 +08:00 via Android 1 比较符合 Python 哲学 |
5 Phishion OP @wuwukai007 我看它文档里面还真是 try 出来的,真原始啊 |
![]() | 6 zeroDev 2021-01-26 19:55:58 +08:00 via Android 应该用 try except 结构,避免判断 参考 Python 官方文档 https://docs.python.org/3.6/glossary.html#term-eafp |
![]() | 10 wuwukai007 2021-01-26 20:04:18 +08:00 你可以这样理解,如果存在的可能新远远大于 不存在,那么使用 try 的性能不就会搞的多吗,不用 try,每次都要判断 |
11 Phishion OP @wuwukai007 有道理,谢谢! |
12 Geek981108 2021-01-26 20:07:29 +08:00 文档如是说: update_or_create() update_or_create(defaults=None, **kwargs) A convenience method for updating an object with the given kwargs, creating a new one if necessary. The defaults is a dictionary of (field, value) pairs used to update the object. The values in defaults can be callables. Returns a tuple of (object, created), where object is the created or updated object and created is a boolean specifying whether a new object was created. The update_or_create method tries to fetch an object from database based on the given kwargs. If a match is found, it updates the fields passed in the defaults dictionary. This is meant as a shortcut to boilerplatish code. For example: defaults = {'first_name': 'Bob'} try: obj = Person.objects.get(first_name='John', last_name='Lennon') for key, value in defaults.items(): setattr(obj, key, value) obj.save() except Person.DoesNotExist: new_values = {'first_name': 'John', 'last_name': 'Lennon'} new_values.update(defaults) obj = Person(**new_values) obj.save() This pattern gets quite unwieldy as the number of fields in a model goes up. The above example can be rewritten using update_or_create() like so: obj, created = Person.objects.update_or_create( first_name='John', last_name='Lennon', defaults={'first_name': 'Bob'}, ) For detailed description how names passed in kwargs are resolved see get_or_create(). As described above in get_or_create(), this method is prone to a race-condition which can result in multiple rows being inserted simultaneously if uniqueness is not enforced at the database level. Like get_or_create() and create(), if you’re using manually specified primary keys and an object needs to be created but the key already exists in the database, an IntegrityError is raised. |
![]() | 13 lixuda 2021-01-26 20:10:52 +08:00 我用这样,不知道性能好不好 article = Article.objects.filter(id=9999).first() if(article): |
16 Austaras 2021-01-27 00:51:32 +08:00 有的数据库支持 upsert |
![]() | 17 chaleaoch 2021-01-27 09:21:57 +08:00 你看源码,其实这俩逻辑差不多. get 里面就是 filter + try catch |
![]() | 18 nonduality 2021-01-27 15:17:55 +08:00 你的方法 2 会引发两次查询,优化文档经常提到不要滥用 exists():如果后续仍需要使用到对象数据,就无须用 exists()去判断对象存在与否。 用 #13 的方法也可以。 |
19 Phishion OP |