如何用Python更快读取SQL Server中约40万行数据?
优化大规模数据读取速度的可行方案
一、Parquet格式的深度优化
- 切换高效压缩算法:默认Parquet常用snappy压缩,可尝试zstd——它压缩比更高且解压速度无明显损耗,创建文件时指定
compression='zstd',读取时pyarrow会自动适配,能减少文件体积,降低IO耗时。 - 精准加载所需列:读取Parquet时明确指定需要的列,避免全量加载冗余数据,进一步缩短读取时间:
df_pq = pq.read_table("\\cluster16.parquet", columns=["Id", "Features", "Edges", "Cluster", "Objects"]) - 预加载缓存到内存:由于集群数量仅1-21个,可在系统启动阶段将所有集群的Parquet数据提前加载到内存字典中,后续查询直接从内存取数,耗时可降至毫秒级,完美适配实时检索场景。
- 优化行组大小:创建Parquet文件时设置合理的
row_group_size(比如10万行左右),让读取时的IO块大小更适配本地存储的性能特性。
二、尝试其他高性能文件格式
- Feather格式:同属Apache Arrow生态,专为内存与磁盘的快速交互设计,读写速度普遍优于Parquet(压缩比略低),适合频繁存取的场景:
写入:
读取:df.to_feather("\\cluster16.feather", compression='zstd')df = pd.read_feather("\\cluster16.feather") - ORC格式:Hadoop生态的列存格式,压缩效率和读取性能均衡,对复杂数据类型支持更完善,pyarrow原生支持读取,可对比测试性能表现。
三、多线程/异步读取优化
- 高频集群预加载:用
concurrent.futures.ThreadPoolExecutor在后台异步预加载用户高频查询的几个集群文件,实际查询时直接取用缓存好的内存数据。 - 异步文件IO:结合
aiofiles和pyarrow的异步读取接口,在高并发的IO密集场景下提升吞吐量,减少查询等待时间。
四、数据库端补充优化(缓存降级方案)
- 创建覆盖索引:如果需要缓存失效时直接查数据库,给
Image表创建包含过滤条件和查询列的覆盖索引,大幅缩短数据库查询耗时:CREATE NONCLUSTERED INDEX IX_Image_Cluster_Filtered ON db.Image (Cluster) INCLUDE (Id, Features, Edges, Objects) WHERE Features IS NOT NULL AND Objects IS NOT NULL; - 按Cluster分区:将
Image表按Cluster字段分区,查询时直接定位到对应分区,减少数据库扫描范围,作为缓存降级的备选方案更高效。
五、内存与数据类型优化
- 压缩DataFrame数据类型:读取后将数据类型转换为更紧凑的格式,比如把
Id设为int32(数值范围允许的话),Features等数组类型用numpy的紧凑类型存储,减少内存占用的同时提升后续处理速度。 - 直接使用pyarrow数据结构:如果后续处理不需要pandas的全部功能,可直接用pyarrow的
Table或DataFrame操作,避免转换到pandas的额外开销,pyarrow的内存效率和处理速度更优。
内容的提问来源于stack exchange,提问作者Johnny
相关产品推荐
相关产品推荐

