【发布时间】:2013-09-29 11:42:21
【问题描述】:
我正在构建一个带有 Oracle 后端的 Django 网站,我发现即使在主键上进行简单的查找时性能也很慢。当在 MySQL 中加载相同的数据时,相同的代码运行速度非常快。
性能不佳的原因可能是什么?我怀疑这个问题与使用Oracle绑定参数有关,但事实可能并非如此。
Django 模型(约 6,200,000 行的测试表)
from django.db import models
class Mytable(models.Model):
upi = models.CharField(primary_key=True, max_length=13)
class Meta:
db_table = 'mytable'
Django ORM(大约需要 1 秒)
from myapp.models import *
r = Mytable.objects.get(upi='xxxxxxxxxxxxx')
带有绑定参数的原始查询(大约需要 1 秒)
cursor.execute("SELECT * FROM mytable WHERE upi = %s", ['xxxxxxxxxxxxx'])
row = cursor.fetchone()
print row
没有绑定参数的原始查询(瞬时)
cursor.execute("SELECT * FROM mytable WHERE upi = 'xxxxxxxxxxxxx'")
row = cursor.fetchone()
print row
我的环境
- Python 2.6.6
- Django 1.5.4
- cx-Oracle 5.1.2
- Oracle 11g
连接到我指定的 Oracle 数据库时:
'OPTIONS': {
'threaded': True,
}
任何帮助将不胜感激。
[更新]
我使用 Django 调试工具栏中的debugsqlshell 工具做了一些进一步的测试。
# takes ~1s
>>>Mytable.objects.get(upi='xxxxxxxxxxxxx')
SELECT "Mytable"."UPI"
FROM "Mytable"
WHERE "Mytable"."UPI" = :arg0 [2.70ms]
这说明Django使用了Oracle绑定参数,查询本身很快,但是创建对应的Python对象需要很长时间。
为了确认,我使用 cx_Oracle 运行了相同的查询(请注意,我最初问题中的 cursor 是 Django cursor)。
import cx_Oracle
db= cx_Oracle.connect('connection_string')
cursor = db.cursor()
# instantaneous
cursor.execute('SELECT * from mytable where upi = :upi', {'upi':'xxxxxxxxxxxxx'})
cursor.fetchall()
什么可能会降低 Django ORM 的速度?
[Update 2] 我们从Oracle端查看了数据库性能,结果发现当查询来自Django时没有使用索引。任何想法为什么会出现这种情况?
【问题讨论】:
-
您是否检查了 db 中存在的查找字段的索引?
-
当我在 SQL Developer 中检查表时,我发现该列上有一个有效的正常索引。
-
如果您在 SQL Developer 中运行这两个版本会发生什么情况,并且查询计划是否不同(使用解释计划或自动跟踪按钮)?对于绑定变量,请使用
SELECT * FROM mytable WHERE upi = :s,SQL Developer 会提示您输入值。 -
@TonyAndrews 两个查询使用相同的执行计划,扫描唯一索引。
-
在 SQL Dev 中两者都是瞬时的?
标签: django oracle orm sqlalchemy cx-oracle