我应首先发出警告,这可能是一个更长的问题。所以请耐心等待。我的一个项目(我最近刚开始)有一个看起来像这样的表
name (varchar)
scores (text)
示例值是这样的 -
['AAA', '[{"score": 3.0, "subject": "Algebra"}, {"score": 5.0, "subject": "geography"}]']
如您所见,第二个字段是JSON数组的字符串表示形式。
我真诚地将此表重新设计为以下两个表格
table-name:
id - Int, auto_inc, primary_key
name - varchar
table-scores:
id - int, auto_inc, primary_key
subject - varchar
score- float
name - int, FK to table-name
我在python文件中有以下代码来表示表(此时,我假设您熟悉Python和SqlAlchemy,因此我将跳过特定的导入,所有这些都会缩短它们)
Base = declarative_base()
class Name(Base):
__tabelname__ = "name_table"
id = Column(Integer, primary_key=True)
name = Column(String(255), index=True)
class Score(Base):
__tablename__ = "score_table"
id = Column(Integer, primary_key=True)
subject = Column(String(255), index=True)
score = Column(Float)
name = Column(ForeignKey('Name.id'), nullable=False, index=True)
Name = relationship(u'Name')
第一个表有~778284行,而第二个表有~907214行。
在声明它们并使用初始数据填充它们后,我去做了一个实验。目标 - 找到分数为>的所有科目。 5.0为给定的名字。 (这里,有一秒钟,请考虑该名称在整个数据库中是唯一的),然后运行相同的过程100次,然后取平均值来查找此查询所花费的时间。以下是我正在做的事情(请想象一下,session是我在调用此函数之前获得的有效数据库会话。)
def test_time():
for i in range(0, 100):
scores = session.query(Score, Name.name).join(Name).filter(Name.name=='AAA').filter(Score.score>5.0).all()
array = []
for score in scores:
array.append((score[0].subject, score[0].score))
我没有对我正在创建的数组做任何事情。但我调用此函数运行此查询100次,我使用default_timer
timeit
来测量已过去的时间。以下是三次运行的结果 -
Avarage - 0.10969632864
Avarage - 0.105748419762
Avarage - 0.105768380165
现在,因为我很好奇,所以我所做的就是我创建了另一个快速而又脏的python文件并在那里宣布了以下课程 -
class DirtyTable(Base):
__tablename__ = "dirty_table"
name = Column(String(255), primary_key=True)
scores = Column(Text)
然后我创建了以下函数来实现相同的目标,但这次从第二个字段读取数据,将其解析回python dict,在列表的所有元素上运行for循环,仅在数组中添加那些得分值>>的元素5.0。在这里 -
def dirty_timer():
for i in range(0,100):
scores = session.query(DirtyTable).filter_by(name='AAA').all()
for score in scores:
x = json.loads(score.scores)
array = []
for member in x:
if x['score'] > 5.0:
array.append((x['subject'], x['score']))
这是三次运行的时间 -
Avarage - 0.0288228917122
Avarage - 0.0296836185455
Avarage - 0.0298663306236
我错过了什么吗?规范化DB(我相信这就是我试图通过打破两个表中的原始表所做的事情)给了我更糟糕的结果。怎么可能。我的方法出了什么问题?
请让我知道你的想法。对不起,很长的帖子,但必须正确解释一切。