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