pandas的read_sql_query和read_sql_table有什么区别?

15

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

import pandas as pd

df=pd.read_sql_query('SELECT * FROM TABLE',conn)
df=pd.read_sql_table(TABLE, conn)
谢谢你的帮助。

我在使用pd.read_sql()pd.read_sql_query()与postgres模式时遇到了麻烦,于是使用了d6tstack.utils.pd_readsql_query_from_sqlengine() - citynorman
4个回答

7

我尝试了无数次,尽管我读到的内容中有很多过程和结论,但我不同意其中大部分。

过程

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

假设

关于假设有句话... 在假设差异不明显与提出无用的考虑pd.read_sql_query之间,这个问题就会严重模糊。唯一的明显的考虑是,如果任何人正在比较pd.read_sql_querypd.read_sql_table,那就是表格,整个表格,而非其他。调用wherejoin等只是浪费时间。

此外,该问题明确要求区分使用SELECT * FROM tableread_sql_tableread_sql_query之间的区别。

我的代码

我在SQLite、MariaDB和PostgreSQL上反复运行了这个代码。我仅使用SQLAlchemy创建引擎,因为pandas需要这样。数据来自coffee-quality-database,我在所有三个引擎中预加载了文件data/arabica_data_cleaned.csv到名为arabica的表中,在名为coffee的数据库中。

以下是我的脚本的概述:

import time
import pandas as pd
from sqlalchemy import create_engine

sqlite_engine = create_engine('sqlite:///coffee.db', echo=False)
mariadb_engine = create_engine('mariadb+mariadbconnector://root:admin@127.0.0.1:3306/coffee')
postgres_engine = create_engine('postgresql://postgres:admin@127.0.0.1:5432/coffee')

for engine in [sqlite_engine, mariadb_engine, postgres_engine]:
    print(engine)
    print('\tpd.read_sql_query:')
    startTime = time.time()
    for i in range(100):
        pd.read_sql_query('SELECT * FROM arabica;', engine)
    print(f"\t[-- TIME --] {time.time()-startTime:.2f} sec\n")
    print('\tpd.read_sql_table:')
    startTime = time.time()
    for i in range(100):
        pd.read_sql_table('arabica', engine)
    print(f"\t[-- TIME --] {time.time()-startTime:.2f} sec\n")

版本如下:

  • Python:3.9.0
  • pandas:1.2.4
  • SQLAlchemy:1.4.13
  • time:内置

我的结果

这是一个样本输出:

Engine(sqlite:///coffee.db)
        pd.read_sql_query:
        [-- TIME --] 2.58 sec

        pd.read_sql_table:
        [-- TIME --] 3.60 sec

Engine(mariadb+mariadbconnector://root:***@127.0.0.1:3306/coffee)
        pd.read_sql_query:
        [-- TIME --] 2.84 sec

        pd.read_sql_table:
        [-- TIME --] 4.15 sec

Engine(postgresql://postgres:***@127.0.0.1:5432/coffee)
        pd.read_sql_query:
        [-- TIME --] 2.18 sec

        pd.read_sql_table:
        [-- TIME --] 4.01 sec

结论

以上是一个样本输出,但我一遍又一遍地运行它,唯一的观察结果是,在每个运行中,pd.read_sql_table 的运行时间总是比 pd.read_sql_query 更长。这听起来非常不合情理,但这就是我们需要隔离问题并在此之前进行测试的原因。

我还没有机会对结果进行适当的统计分析,但乍一看,我敢于说这些差异是显著的,因为两个“列”(querytable 的时间)都在接近范围内返回,并且两者之间距离很大。在某些运行中,table 对于某些引擎需要的时间是query所需时间的两倍。

如果有机会运行这样的分析,我将用结果和matplotlib证据补充这个答案。

背景

我的初衷是调查表达数千列数据时 SQL 与 MongoDB 的适用性。来自pdmongo包的pdmongo.read_mongo使pd.read_sql_table相形见绌——后者对于大型表格的性能表现非常差,但它仍不及pd.read_sql_query

在大约 900 列的情况下,pd.read_sql_query 的表现比 pd.read_sql_table 快 5 至 10 倍!


刚刚在一个大约有125,000行的表上进行了测试,使用的是pandas 2.1.0和SQLAlchemy 2.0.20。
  • read_sql_query("SELECT * FROM table") 大约花费了100秒
  • read_sql_table(table_name) 大约花费了200秒
- undefined

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)

并且。
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)

注意:我故意删掉了文档字符串...


好的,那么哪一个是推荐的? - NoName
@NoName,使用最舒适的那个吧 ;) - MaxU - stand with Ukraine

1
主要区别显而易见,
使用
df=pd.read_sql_query('SELECT * FROM TABLE',conn)
时,您使用的是可以复杂的 SQL 查询,因此执行可能需要很多时间/资源。

使用
df=pd.read_sql_table(TABLE, conn)
您可以下载一个表并仅指定列、模式等。

1
在read_sql_query中,您可以添加where子句,添加连接等,以此减少从数据库移动到数据框中的数据量。如果您有一个巨大的表格,并且只需要少量行,则更好。另一方面,如果您的表很小,请使用read_sql_table,并在Python中操作数据框。它比SQL更灵活。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接