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