熊猫读取SQL查询和读取SQL表之间的区别

Ous*_*bri 6 python sql sqlite dataframe pandas

这两个命令之间在时间执行方面有区别:

import pandas as pd

df=pd.read_sql_query('SELECT * FROM TABLE',conn)
df=pd.read_sql_table(TABLE, conn)
Run Code Online (Sandbox Code Playgroud)

谢谢您的帮助

Ric*_*rdo 8

我尝试了无数次,尽管我读到了上面的内容,但我不同意大部分过程或结论。

\n

过程

\n

如果您要比较两种方法,添加厚厚的SQLAlchemyor层pandasSQL_builder(即pandas.io.sql.pandasSQL_builder,没有import)和其他此类非独立片段至少可以说是没有帮助的。在没有噪音的情况下比较两种方法的唯一方法是尽可能干净地使用它们,并且至少在类似的情况下使用它们。

\n

假设

\n

有一种关于假设的说法……在假设差异不明显和提出无用的考虑之间pd.read_sql_query,这一点变得严重模糊。这里唯一明显的考虑因素是,如果有人要比较pd.read_sql_querypd.read_sql_table,那就是表,整个表,除了表之外什么都没有。调用where,join和其他人只是浪费时间。

\n

read_sql_table此外,该问题明确询问了 a和read_sql_querya之间的区别SELECT * FROM table

\n

我的代码

\n

我在 SQLite、MariaDB 和 PostgreSQL 上一遍又一遍地运行这个。我SQLAlchemy专门用来创建引擎,因为pandas需要这个。数据来自咖啡质量数据库,我在所有三个引擎中预加载该文件到一个名为的数据库中data/arabica_data_cleaned.csv调用的表arabicacoffee

\n

这是我的脚本的摘要版本:

\n
import time\nimport pandas as pd\nfrom sqlalchemy import create_engine\n\nsqlite_engine = create_engine(\'sqlite:///coffee.db\', echo=False)\nmariadb_engine = create_engine(\'mariadb+mariadbconnector://root:admin@127.0.0.1:3306/coffee\')\npostgres_engine = create_engine(\'postgresql://postgres:admin@127.0.0.1:5432/coffee\')\n\nfor engine in [sqlite_engine, mariadb_engine, postgres_engine]:\n    print(engine)\n    print(\'\\tpd.read_sql_query:\')\n    startTime = time.time()\n    for i in range(100):\n        pd.read_sql_query(\'SELECT * FROM arabica;\', engine)\n    print(f"\\t[-- TIME --] {time.time()-startTime:.2f} sec\\n")\n    print(\'\\tpd.read_sql_table:\')\n    startTime = time.time()\n    for i in range(100):\n        pd.read_sql_table(\'arabica\', engine)\n    print(f"\\t[-- TIME --] {time.time()-startTime:.2f} sec\\n")\n
Run Code Online (Sandbox Code Playgroud)\n

版本是:

\n
    \n
  • 蟒蛇:3.9.0
  • \n
  • 熊猫:1.2.4
  • \n
  • SQLAlchemy:1.4.13
  • \n
  • 时间:内置
  • \n
\n

我的结果

\n

这是一个示例输出:

\n
Engine(sqlite:///coffee.db)\n        pd.read_sql_query:\n        [-- TIME --] 2.58 sec\n\n        pd.read_sql_table:\n        [-- TIME --] 3.60 sec\n\nEngine(mariadb+mariadbconnector://root:***@127.0.0.1:3306/coffee)\n        pd.read_sql_query:\n        [-- TIME --] 2.84 sec\n\n        pd.read_sql_table:\n        [-- TIME --] 4.15 sec\n\nEngine(postgresql://postgres:***@127.0.0.1:5432/coffee)\n        pd.read_sql_query:\n        [-- TIME --] 2.18 sec\n\n        pd.read_sql_table:\n        [-- TIME --] 4.01 sec\n
Run Code Online (Sandbox Code Playgroud)\n

结论

\n

上面是一个示例输出,但我一遍又一遍地运行它,唯一的观察结果是,在每次运行中pd.read_sql_table 总是花费比pd.read_sql_query. 这听起来非常违反直觉,但这就是为什么我们在在这里倾注知识之前实际上隔离了问题并进行测试的原因。

\n

我还没有机会对结果进行适当的统计分析,但乍一看,我冒着指出差异很大的风险,因为两个“列”(querytable时间)都在接近的范围内返回(从运行跑)并且距离都相当远。在某些运行中,table某些引擎需要花费两倍的时间。

\n

如果/当我有机会进行这样的分析时,我将用结果和证据来补充这个答案matplotlib

\n

语境

\n

我最初的想法是研究当表达到数千列时 SQL 与 MongoDB 的适用性。pdmongo.read_mongo(来自pdmongo包)破坏了pd.read_sql_table\xe2\x80\x94 ,它对大型表 \xe2\x80\x94 的性能非常差,但达不到pd.read_sql_query.

\n

大约 900 列,pd.read_sql_query性能提高pd.read_sql_table5 到 10 倍!

\n


Max*_*axU 2

我认为您不会注意到这种差异。

这是两个函数的源代码:

In [398]: pd.read_sql_query??
Signature: pd.read_sql_query(sql, con, index_col=None, coerce_float=True, params=None, parse_dates=None, chunksize=None)
Source:
def read_sql_query(sql, con, index_col=None, coerce_float=True, params=None,
                   parse_dates=None, chunksize=None):
    pandas_sql = pandasSQL_builder(con)
    return pandas_sql.read_query(
        sql, index_col=index_col, params=params, coerce_float=coerce_float,
        parse_dates=parse_dates, chunksize=chunksize)
Run Code Online (Sandbox Code Playgroud)

In [399]: pd.read_sql_table??
Signature: pd.read_sql_table(table_name, con, schema=None, index_col=None, coerce_float=True, parse_dates=None, columns=None, chunksize=None
)
Source:
def read_sql_table(table_name, con, schema=None, index_col=None,
                   coerce_float=True, parse_dates=None, columns=None,
                   chunksize=None):
    con = _engine_builder(con)
    if not _is_sqlalchemy_connectable(con):
        raise NotImplementedError("read_sql_table only supported for "
                                  "SQLAlchemy connectable.")
    import sqlalchemy
    from sqlalchemy.schema import MetaData
    meta = MetaData(con, schema=schema)
    try:
        meta.reflect(only=[table_name], views=True)
    except sqlalchemy.exc.InvalidRequestError:
        raise ValueError("Table %s not found" % table_name)

    pandas_sql = SQLDatabase(con, meta=meta)
    table = pandas_sql.read_table(
        table_name, index_col=index_col, coerce_float=coerce_float,
        parse_dates=parse_dates, columns=columns, chunksize=chunksize)

    if table is not None:
        return table
    else:
        raise ValueError("Table %s not found" % table_name, con)
Run Code Online (Sandbox Code Playgroud)

注意:我故意切断了文档字符串......