python - 如何减少 sqlalchemy 用于连接数据库和选择数据的时间

标签 python mysql orm sqlalchemy pymysql

我是数据科学的初学者,我最近的工作是使用 python 从公司数据库中选择符合某些条件的数据。我尝试通过使用 sqlalchemy 和引擎来实现此目的,但是获取我需要的所有行需要很长时间。我不知道我能做些什么来减少它的执行时间。 例如,我使用以下代码根据数据库中的store_id获取商店在一段时间内的总订单数:

import pandas as pd
from sqlalchemy import create_engine, MetaData, select, Table, func, and_, or_, cast, Float
import pymysql

#create engine and connect it to the database
engine = create_engine('mysql+pymysql://root:*******@127.0.0.1:3306/db')
order = Table('order', metadata, autoload=True, autoload_with=engine)


#use the store_id to get all the data in two months from the table
def order_df_func(store_id):     
    df = pd.DataFrame()
    stmt = select([order.columns.gmt_create, order.columns.delete_status, order.columns.payment_time])
    stmt = stmt.where(
        and_(order.columns.store_id == store_id,
             order.columns.gmt_create <= datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
             order.columns.gmt_create >= get_day_zero(last_month_start.date()) #func defined to get 00:00 for a day
                )
        )
    results = connection.execute(stmt).fetchall()
    df = pd.DataFrame(results)
    df.columns = results[0].keys()
    return df

#get the data in a specific time period
def time_bounded_order_df(store_id, date_required_type, time_period):
    order_df = order_df_func(store_id)
    get_date(date_required_type)# func defined to get the start time and end time, e.g. this week or this month
    if time_period == 't':
        order_df = order_df[(order_df['gmt_create'].astype(str) >= start_time) & (order_df['gmt_create'].astype(str) <= end_time)]
    elif time_period == 'l':
        order_df = order_df[(order_df['gmt_create'].astype(str) >= last_period_start_time) & (order_df['gmt_create'].astype(str) <= last_period_end_time)]
    return order_df

#get the number or orders
def num_of_orders(df):
    return len(df.index)

40万条结果大约需要8s,时间太长了。我是否可以调整我的代码以使其更短?

更新

我尝试直接在mysql工作台中选择数据,大约需要0.02s才能得到1000条结果。我相信这个问题来自下面的代码

results = connection.execute(stmt).fetchall()

但我不知道我可以将数据存储到 pd.dataframe 中。有什么想法吗?

更新2

我刚刚了解到表中有一种称为“索引”的东西可以减少处理时间。我的数据库是公司给的,我无法编辑。我不确定这是否是数据库中表的问题,或者我仍然需要做一些事情来修复我的代码。有没有办法可以在我的代码中“使用”索引?还是应该给?或者我可以通过python创建索引吗?

更新3

我发现当我选择多个列时,我的数据库停止使用索引,这显着增加了处理时间。我相信这是一个 mysql 问题而不是 python 问题。我仍在寻找如何解决这个问题,因为我几乎不了解 sql。

更新4

我将 mysql 服务器版本从 8.0 降级到 5.7,表中的索引开始工作。但python处理起来还是需要很长的时间。我会继续努力找出我能为此做些什么。

最佳答案

我发现如果我使用

results = connection.execute(stmt).fetchall()
df = pd.DataFrame(results)
df.columns = results[0].keys()

然后你将数据库中的所有数据重新保存到python中,由于我没有为python创建索引,所以重新保存时间和搜索时间都很长。然而,就我而言,我不需要在 python 中重新保存数据,我只需要几个变量的总数。因此,我没有选择几列,而是使用

stmt = select([func.count(yc_order.columns.id)])
#where something something
results = connection.execute(stmt).scalar()
return results

它的运行速度和mysql内部一样快,问题就解决了

附注我还需要一些变量来计算每小时的总订单数。我决定在数据库中创建一个新表,并使用计划模块每小时运行脚本并将数据插入新表中。

关于python - 如何减少 sqlalchemy 用于连接数据库和选择数据的时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58831159/

相关文章:

python - 计算两个旋转椭圆的交集/并集?

python - 如何将包含多个字典的列表转换为字典

java - JPA:一对多关系中阻抗不匹配的问题

java - Hibernate 中 session.flush() 有什么用

python - 初始化字体需要很长时间

Python 和直接访问命令行实用程序 ifconfig、iwconfig 和 iw

php - 问答论坛 - 逻辑

mysql - 只为一个 Bundle 创建的 Doctrine Schema

mysql_query 在循环时仅执行一次 - php

mysql - 如何区分目标表和源表?