1 如何 在做ORM查询时 查看SQl的执行情况
(1) 最底层的 django.db.connection
在 django shell 中使用 python manage.py shell
1
2
3
4
5
|
>>> from django.db import connection >>> Books.objects. all () >>> connection.queries ## 可以查看查询时间 [{ 'sql' : 'SELECT "testsql_books" . "id" , "testsql_books" . "name" , "testsql_books" . "author_id" FROM "testsql_books" LIMI T 21 ', ' time ': ' 0.002 '}] |
(2) django-extensions 插件
1
|
pip install django - extensions |
1
2
3
4
5
|
INSTALLED_APPS = ( ... 'django_extensions' , ... ) |
在 django shell 中使用 python manage.py shell_plus --print-sql (extensions 强化)
这样每次查询都会 有sql 输出
1
2
3
4
5
6
7
|
>>> Books.objects. all () SELECT "testsql_books" . "id" , "testsql_books" . "name" , "testsql_books" . "author_id" FROM "testsql_books" LIMIT 21 Execution time: 0.002000s [Database: default] <QuerySet [<Books: Books object >, <Books: Books object >, <Books: Books object >]> |
2 ORM查询操作 以及优化
基本操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
增 models.Tb1.objects.create(c1 = 'xx' , c2 = 'oo' ) 增加一条数据,可以接受字典类型数据 * * kwargs obj = models.Tb1(c1 = 'xx' , c2 = 'oo' ) obj.save() 查 models.Tb1.objects.get( id = 123 ) # 获取单条数据,不存在则报错(不建议) models.Tb1.objects. all () # 获取全部 models.Tb1.objects. filter (name = 'seven' ) # 获取指定条件的数据 models.Tb1.objects.exclude(name = 'seven' ) # 获取指定条件的数据 删 models.Tb1.objects. filter (name = 'seven' ).delete() # 删除指定条件的数据 改 models.Tb1.objects. filter (name = 'seven' ).update(gender = '0' ) # 将指定条件的数据更新,均支持 **kwargs obj = models.Tb1.objects.get( id = 1 ) obj.c1 = '111' obj.save() # 修改单条数据 |
查询简单操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
获取个数 models.Tb1.objects. filter (name = 'seven' ).count() 大于,小于 models.Tb1.objects. filter (id__gt = 1 ) # 获取id大于1的值 models.Tb1.objects. filter (id__gte = 1 ) # 获取id大于等于1的值 models.Tb1.objects. filter (id__lt = 10 ) # 获取id小于10的值 models.Tb1.objects. filter (id__lte = 10 ) # 获取id小于10的值 models.Tb1.objects. filter (id__lt = 10 , id__gt = 1 ) # 获取id大于1 且 小于10的值 in models.Tb1.objects. filter (id__in = [ 11 , 22 , 33 ]) # 获取id等于11、22、33的数据 models.Tb1.objects.exclude(id__in = [ 11 , 22 , 33 ]) # not in isnull Entry.objects. filter (pub_date__isnull = True ) contains models.Tb1.objects. filter (name__contains = "ven" ) models.Tb1.objects. filter (name__icontains = "ven" ) # icontains大小写不敏感 models.Tb1.objects.exclude(name__icontains = "ven" ) range models.Tb1.objects. filter (id__range = [ 1 , 2 ]) # 范围bettwen and 其他类似 startswith,istartswith, endswith, iendswith, order by models.Tb1.objects. filter (name = 'seven' ).order_by( 'id' ) # asc models.Tb1.objects. filter (name = 'seven' ).order_by( '-id' ) # desc group by - - annotate from django.db.models import Count, Min , Max , Sum models.Tb1.objects. filter (c1 = 1 ).values( 'id' ).annotate(c = Count( 'num' )) SELECT "app01_tb1" . "id" , COUNT( "app01_tb1" . "num" ) AS "c" FROM "app01_tb1" WHERE "app01_tb1" . "c1" = 1 GROUP BY "app01_tb1" . "id" limit 、offset models.Tb1.objects. all ()[ 10 : 20 ] regex正则匹配,iregex 不区分大小写 Entry.objects.get(title__regex = r '^(An?|The) +' ) Entry.objects.get(title__iregex = r '^(an?|the) +' ) date Entry.objects. filter (pub_date__date = datetime.date( 2005 , 1 , 1 )) Entry.objects. filter (pub_date__date__gt = datetime.date( 2005 , 1 , 1 )) year Entry.objects. filter (pub_date__year = 2005 ) Entry.objects. filter (pub_date__year__gte = 2005 ) month Entry.objects. filter (pub_date__month = 12 ) Entry.objects. filter (pub_date__month__gte = 6 ) day Entry.objects. filter (pub_date__day = 3 ) Entry.objects. filter (pub_date__day__gte = 3 ) week_day Entry.objects. filter (pub_date__week_day = 2 ) Entry.objects. filter (pub_date__week_day__gte = 2 ) hour Event.objects. filter (timestamp__hour = 23 ) Event.objects. filter (time__hour = 5 ) Event.objects. filter (timestamp__hour__gte = 12 ) minute Event.objects. filter (timestamp__minute = 29 ) Event.objects. filter (time__minute = 46 ) Event.objects. filter (timestamp__minute__gte = 29 ) second Event.objects. filter (timestamp__second = 31 ) Event.objects. filter (time__second = 2 ) Event.objects. filter (timestamp__second__gte = 31 ) |
查询复杂操作
FK foreign key 使用的原因:
- 约束
- 节省硬盘
但是多表查询会降低速度,大型程序反而不使用外键,而是用单表(约束的时候,通过代码判断)
extra
1
2
3
4
5
|
extra( self , select = None , where = None , params = None , tables = None , order_by = None , select_params = None ) Entry.objects.extra(select = { 'new_id' : "select col from sometable where othercol > %s" }, select_params = ( 1 ,)) Entry.objects.extra(where = [ 'headline=%s' ], params = [ 'Lennon' ]) Entry.objects.extra(where = [ "foo='a' OR bar = 'a'" , "baz = 'a'" ]) Entry.objects.extra(select = { 'new_id' : "select id from tb where id > %s" }, select_params = ( 1 ,), order_by = [ '-nid' ]) |
F
1
2
|
from django.db.models import F models.Tb1.objects.update(num = F( 'num' ) + 1 ) |
Q
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
方式一: Q(nid__gt = 10 ) Q(nid = 8 ) | Q(nid__gt = 10 ) Q(Q(nid = 8 ) | Q(nid__gt = 10 )) & Q(caption = 'root' ) 方式二: con = Q() q1 = Q() q1.connector = 'OR' q1.children.append(( 'id' , 1 )) q1.children.append(( 'id' , 10 )) q1.children.append(( 'id' , 9 )) q2 = Q() q2.connector = 'OR' q2.children.append(( 'c1' , 1 )) q2.children.append(( 'c1' , 10 )) q2.children.append(( 'c1' , 9 )) con.add(q1, 'AND' ) con.add(q2, 'AND' ) models.Tb1.objects. filter (con) |
exclude(self, *args, **kwargs)
1
2
|
# 条件查询 # 条件可以是:参数,字典,Q |
select_related(self, *fields)
1
2
3
4
|
性能相关:表之间进行join连表操作,一次性获取关联的数据。 model.tb.objects. all ().select_related() model.tb.objects. all ().select_related( '外键字段' ) model.tb.objects. all ().select_related( '外键字段__外键字段' ) |
prefetch_related(self, *lookups)
1
2
3
4
|
性能相关:多表连表操作时速度会慢,使用其执行多次SQL查询 在内存中做关联,而不会再做连表查询 # 第一次 获取所有用户表 # 第二次 获取用户类型表where id in (用户表中的查到的所有用户ID) models.UserInfo.objects.prefetch_related( '外键字段' ) |
annotate(self, *args, **kwargs)
1
2
3
4
5
6
7
8
9
10
11
12
|
# 用于实现聚合group by查询 from django.db.models import Count, Avg, Max , Min , Sum v = models.UserInfo.objects.values( 'u_id' ).annotate(uid = Count( 'u_id' )) # SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id v = models.UserInfo.objects.values( 'u_id' ).annotate(uid = Count( 'u_id' )). filter (uid__gt = 1 ) # SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 v = models.UserInfo.objects.values( 'u_id' ).annotate(uid = Count( 'u_id' ,distinct = True )). filter (uid__gt = 1 ) # SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 |
extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
1
2
3
4
5
6
|
# 构造额外的查询条件或者映射,如:子查询 Entry.objects.extra(select = { 'new_id' : "select col from sometable where othercol > %s" }, select_params = ( 1 ,)) Entry.objects.extra(where = [ 'headline=%s' ], params = [ 'Lennon' ]) Entry.objects.extra(where = [ "foo='a' OR bar = 'a'" , "baz = 'a'" ]) Entry.objects.extra(select = { 'new_id' : "select id from tb where id > %s" }, select_params = ( 1 ,), order_by = [ '-nid' ]) |
reverse(self):
1
2
3
|
# 倒序 models.UserInfo.objects. all ().order_by( '-nid' ).reverse() # 注:如果存在order_by,reverse则是倒序,如果多个排序则一一倒序 |
下面两个 取到的是对象,并且注意 取到的对象可以 获取其他字段(这样会再去查找该字段降低性能
defer(self, *fields):
1
2
3
4
|
models.UserInfo.objects.defer( 'username' , 'id' ) 或 models.UserInfo.objects. filter (...).defer( 'username' , 'id' ) # 映射中排除某列数据 |
only(self, *fields):
1
2
3
4
|
# 仅取某个表中的数据 models.UserInfo.objects.only( 'username' , 'id' ) 或 models.UserInfo.objects. filter (...).only( 'username' , 'id' ) |
执行原生SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
1.connection from django.db import connection, connections cursor = connection.cursor() # cursor = connections['default'].cursor() django的settings中的db配置 ' default' ,指定数据库 cursor.execute( """SELECT * from auth_user where id = %s""" , [ 1 ]) row = cursor.fetchone() 2 .extra Entry.objects.extra(select = { 'new_id' : "select id from tb where id > %s" }, select_params = ( 1 ,), order_by = [ '-nid' ]) 3 . raw name_map = { 'a' : 'A' , 'b' : 'B' } models.UserInfo.objects.raw( 'select * from xxxx' ,translations = name_map) |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://www.cnblogs.com/big-handsome-guy/p/8533908.html