MySQL,join vs string parsing

时间:2016-12-02 20:42:57

标签: python mysql json sqlalchemy performance-testing

我应首先发出警告,这可能是一个更长的问题。所以请耐心等待。我的一个项目(我最近刚开始)有一个看起来像这样的表

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(我相信这就是我试图通过打破两个表中的原始表所做的事情)给了我更糟糕的结果。怎么可能。我的方法出了什么问题?

请让我知道你的想法。对不起,很长的帖子,但必须正确解释一切。

0 个答案:

没有答案