数据库设计远非最佳,但我必须处理它,现在我真的被卡住了。
编辑:我正在使用cx_Oracle
好的,这是我的疑问:
query="select degree, spectraldev.event.eventnumber \
from spectraldev.degree \
join spectraldev.alignment on \
(spectraldev.version_id = alignment.version_id) \
join spectraldev.event on \
(alignment.timestamp between event.eventstart and event.eventstop) \
join spectraldev.eventsetup on \
(spectraldev.event.eventsetup = spectraldev.eventsetup.oid) \
where spectraldev.event.eventnumber>=" + options.start + " AND spectraldev.event.eventnumber<=" + options.stop + " AND \
HITS>=" + str(options.minimum_hits)+" \
order by spectraldev.event.eventnumber"
db_cursor.execute(query)
为许多事件返回一堆degree
s(12.34等),这些事件由唯一编号(eventnumber
如346554)标识。
所以我得到一张这样的表:
454544 45.2
454544 12.56
454544 41.1
454544 45.4
454600 22.3
454600 24.13
454600 21.32
454600 22.53
454600 54.51
454600 33.87
454610 32.7
454610 12.99
等等......
现在我需要为每个事件创建一个带有平均度的字典(总结所有相应的浮点数并除以它们的数量)。
我认为这可以在SQL中完成,但我无法让它工作。目前我正在使用python执行此操作,但是fetch命令需要1-2个小时来完成大约2000个事件,这太慢了,因为我需要处理大约1000000个事件。
这是我的提取部分,需要很长时间:
_degrees = []
for degree, eventNumber in cursor.fetchall():
_degrees.append([eventNumber, degree])
然后排序(这真的很快,<1秒)并计算平均值(也非常快):
_d={}
for eventNumber, degree in _degrees:
_d.setdefault(eventNumber, []).append(degree)
for event in events:
_curDegree = _degrees[int(event)]
_meanDegree = sum(_curDegree) / float(len(_curDegree))
meanDegrees.append(_meanDegree)
有没有办法在SQL中执行python部分?
答案 0 :(得分:1)
这是一个旁边,但重要的一个。您对SQL Injection非常开放。 可能在您的特定实例中无关紧要,但最好总是编写最差的代码。
您没有提到您正在使用的模块,但假设它符合PEP 249(您可能正在使用cx_Oracle),那么您可以传递带有命名绑定参数的字典。典型的查询可能如下所示:
query = """select column1 from my_table where id = :my_id"""
bind_vars = {'my_id' : 1}
db_cursor.execute(query, bind_vars)
在实际查询中,您将一些变量(例如options.start
)转换为Python中的字符串,但不在SQL中引用它们,这意味着它们被隐式转换回数字。这几乎绝对不需要。
关于你的实际问题1-2小时完成2000个事件,你是对的,很荒谬。您尚未发布架构,但我的猜测是您缺少任何indexes。
要获得每个事件编号的平均学位数,您应该使用avg()
函数。这将使您的查询:
select spectraldev.event.eventnumber, avg(degree) as degree
from spectraldev.degree
join spectraldev.alignment
-- I think this is wrong on your query
on (degree.version_id = alignment.version_id)
join spectraldev.event
on (alignment.timestamp between event.eventstart and event.eventstop)
join spectraldev.eventsetup
on (spectraldev.event.eventsetup = spectraldev.eventsetup.oid)
where spectraldev.event.eventnumber >= :start
and spectraldev.event.eventnumber <= :stop
and hits >= :minimum_hits
group by spectraldev.event.eventnumber
order by spectraldev.event.eventnumber
我已经对您的查询进行了格式化,使其更具可读性(从我的角度来看),并使您在需要索引时更加明显。
由此判断,您需要对以下表格和列进行索引;
eventnumber
,eventstart
,eventstop
,eventsetup
version_id
version_id
,tstamp
oid
以及hits
可能在哪里。
说完所有问题可能 索引。您尚未提供解释计划或架构或行数,因此这将是一个猜测。但是,如果您在表中选择了很大一部分行,那么CBO 可能正在使用索引。例如,使用full hint,/*+ full(event) */
强制进行全表扫描可能会解决您的问题。
删除order by
,如果不需要,也可以显着加快查询速度。