找回密码
 立即注册
首页 业界区 业界 在超大数据集下 DuckDB 与 MySQL 查询速度对比 ...

在超大数据集下 DuckDB 与 MySQL 查询速度对比

周濡霈 昨天 22:15
本文介绍在本地同样配置的PC中,使用同样体量的数据集,对比DuckDB与MySQL的对不同SQL语句场景地查询速度表现。结果是大多数业务需求场景下,DuckDB的查询速度基本都比MySQL快10倍左右。
PC配置:24核64GB内存
mysql版本:8.0.12
duckdb版本:1.5.1
python版本:3.12.10
 
数据集说明
  数据集获取:https://tooli.fun/resource_detail?resource_id=330

  • 核心数据表:stock_daily
  • 数据行数:14150202
  • 导出CSV大小: 1.15GB
  • 数据表结构:
  1. CREATE TABLE `stock_daily` (
  2.   `ts_code` varchar(10) NOT NULL COMMENT '股票代码',
  3.   `trade_date` datetime NOT NULL COMMENT '交易日期',
  4.   `open` float DEFAULT NULL COMMENT '开盘价',
  5.   `high` float DEFAULT NULL COMMENT '最高价',
  6.   `low` float DEFAULT NULL COMMENT '最低价',
  7.   `close` float DEFAULT NULL COMMENT '收盘价',
  8.   `pre_close` float DEFAULT NULL COMMENT '昨收价',
  9.   `change` float DEFAULT NULL COMMENT '涨跌额',
  10.   `pct_chg` float DEFAULT NULL COMMENT '涨跌幅(未复权)',
  11.   `vol` float DEFAULT NULL COMMENT '成交量(手)',
  12.   `amount` float DEFAULT NULL COMMENT '成交额(千元)',
  13.   `adj_factor` float DEFAULT NULL COMMENT '复权因子(前复权QFQ=当日收盘价×当日复权因子/最新复权因子,后复权HFQ=当日收盘价×当日复权因子)',
  14.   PRIMARY KEY (`ts_code`,`trade_date`),
  15.   KEY `idx_trade_date` (`trade_date`)
  16. ) ENGINE=InnoDB DEFAULT CHARSET=utf8
复制代码
1.webp

 

  • 维度表:stock_base
  • 数据行数:5362
  • 导出CSV大小: 1.12MB
  • 数据表结构:
  1. CREATE TABLE `stock_base` (
  2.   `ts_code` varchar(10) NOT NULL COMMENT 'TS代码',
  3.   `symbol` varchar(10) DEFAULT NULL COMMENT '股票代码',
  4.   `name` varchar(64) DEFAULT NULL COMMENT '股票名称',
  5.   `area` varchar(64) DEFAULT NULL COMMENT '地域',
  6.   `industry` varchar(64) DEFAULT NULL COMMENT '所属行业',
  7.   `fullname` varchar(255) DEFAULT NULL COMMENT '股票全称',
  8.   `enname` varchar(255) DEFAULT NULL COMMENT '英文全称',
  9.   `cnspell` varchar(64) DEFAULT NULL COMMENT '拼音缩写',
  10.   `market` varchar(64) DEFAULT NULL COMMENT '市场类型(主板/创业板/科创板/CDR)',
  11.   `exchange` varchar(64) DEFAULT NULL COMMENT '交易所代码',
  12.   `curr_type` varchar(16) DEFAULT NULL COMMENT '交易货币',
  13.   `list_status` varchar(16) DEFAULT NULL COMMENT '上市状态 L上市 D退市 P暂停上市',
  14.   `list_date` datetime DEFAULT NULL COMMENT '上市日期',
  15.   `delist_date` datetime DEFAULT NULL COMMENT '退市日期',
  16.   `is_hs` varchar(16) DEFAULT NULL COMMENT '是否沪深港通标的,N否 H沪股通 S深股通',
  17.   PRIMARY KEY (`ts_code`)
  18. ) ENGINE=InnoDB DEFAULT CHARSET=utf8
复制代码
2.webp

 
 

  • 维度表:stock_company
  • 数据行数:5146
  • 导出CSV大小: 9.9MB
  • 数据表结构:
  1. CREATE TABLE `stock_company` (
  2.   `ts_code` varchar(10) NOT NULL COMMENT '股票代码',
  3.   `exchange` varchar(10) DEFAULT NULL COMMENT '交易所代码 ,SSE上交所 SZSE深交所',
  4.   `chairman` varchar(64) DEFAULT NULL COMMENT '法人代表',
  5.   `manager` varchar(64) DEFAULT NULL COMMENT '总经理',
  6.   `secretary` varchar(64) DEFAULT NULL COMMENT '董秘',
  7.   `reg_capital` float DEFAULT NULL COMMENT '注册资本',
  8.   `setup_date` datetime DEFAULT NULL COMMENT '注册日期',
  9.   `province` varchar(64) DEFAULT NULL COMMENT '所在省份',
  10.   `city` varchar(64) DEFAULT NULL COMMENT '所在城市',
  11.   `introduction` text COMMENT '公司介绍',
  12.   `website` varchar(255) DEFAULT NULL COMMENT '公司主页',
  13.   `email` varchar(64) DEFAULT NULL COMMENT '电子邮件',
  14.   `office` varchar(255) DEFAULT NULL COMMENT '办公室',
  15.   `business_scope` text COMMENT '经营范围',
  16.   `employees` int(11) DEFAULT NULL COMMENT '员工人数',
  17.   `main_business` text COMMENT '主要业务及产品',
  18.   PRIMARY KEY (`ts_code`)
  19. ) ENGINE=InnoDB DEFAULT CHARSET=utf8
复制代码
3.webp

 
 
SQL运行对比
 
SQL:统计数据量
  1. -- MySQL查询,耗时:8.038秒
  2. select COUNT(*) from stock_daily;
  3. -- DuckDB 查询CSV文件 耗时:0.452秒
  4. select count(*) from 'e:/data/data_set/stock/stock_daily.csv';
复制代码
4.webp


SQL:按实际股票分组统计每只股票的交易天数
  1. -- MySQL查询,耗时:2.627秒
  2. SELECT ts_code,COUNT(*) FROM stock_daily GROUP BY ts_code;
  3. -- DuckDB查询CSV文件, 耗时:0.478秒
  4. SELECT ts_code,COUNT(*) FROM 'e:/data/data_set/stock/stock_daily.csv' GROUP BY ts_code;
复制代码
5.webp

 

SQL:按实际股票分组统计每只股票的交易天数,并按照天数排序
  1. -- MySQL查询,耗时:13.16秒
  2. SELECT ts_code,COUNT(*) AS days FROM stock_daily GROUP BY ts_code ORDER BY days;
  3. -- DuckDB查询,耗时:0.495秒
  4. SELECT ts_code,COUNT(*) AS days FROM 'e:/data/data_set/stock/stock_daily.csv' GROUP BY ts_code ORDER BY days;
复制代码
6.webp

7.webp

 
SQL:查询2020年5月7号上涨的股票数量(收盘价>开盘价)
  1. -- MySQL查询, 耗时:4.194秒
  2. SELECT COUNT(*) AS up FROM stock_daily WHERE trade_date='2020-05-07 00:00:00' and `close` > `open`;
  3. -- DuckDB查询, 耗时:0.511秒
  4. result = conn.execute("""
  5. SELECT COUNT(*) AS up FROM read_csv(
  6.     'e:/data/data_set/stock/stock_daily.csv',
  7.     auto_detect = true,
  8.     nullstr = ['\\N']
  9.     )
  10. WHERE trade_date = DATE '2020-05-07' and close>open;
  11. """).fetchall()
复制代码
8.webp

 
SQL:查询2020年5月7号上涨的股票数量,按照行业分组
特点:读取2个csv文件,left join 一次
  1. -- MySQL查询, 耗时:4.705秒
  2. SELECT b.industry,COUNT(*) AS up FROM stock_daily a LEFT JOIN stock_base b ON a.ts_code = b.ts_code WHERE a.trade_date='2020-05-07 00:00:00' AND a.`close` > a.`open` GROUP BY b.industry ORDER BY up DESC;
  3. -- DuckDB查询, 耗时:0.596秒
  4. SELECT b.industry,COUNT(*) AS up FROM read_csv(
  5.     'e:/data/data_set/stock/stock_daily.csv',
  6.     auto_detect =true,
  7.     nullstr = ['\\N']
  8.     ) a leftjoin
  9.     read_csv(
  10.         'e:/data/data_set/stock/stock_base.csv',
  11.         auto_detect =true,
  12.         nullstr = ['\\N']
  13.         ) b
  14. ON a.ts_code = b.ts_code
  15. WHERE a.trade_date =DATE'2020-05-07'AND a.close>a.open
  16. GROUPBY b.industry ORDERBY up DESC;
复制代码
9.webp

 
 
SQL:查询2020年5月7号上涨的股票数量,按交易所和行业分组
特点:读取3个csv文件,left join 两次,
  1. -- MySQL查询, 耗时:4.705秒
  2. SELECT c.exchange,b.industry,COUNT(*) AS up FROM stock_daily a LEFT JOIN stock_base b ON a.ts_code = b.ts_code LEFT JOIN stock_company c ON a.ts_code=c.ts_code WHERE a.trade_date='2020-05-07 00:00:00' AND a.close>a.open GROUP BY c.exchange,b.industry ORDER BY up DESC;
  3. --DuckDB查询, 耗时:0.883秒
  4. SELECT c.exchange,b.industry,COUNT(*) AS up FROM read_csv(
  5.     'e:/data/data_set/stock/stock_daily.csv',
  6.     auto_detect = true,
  7.     nullstr = ['\\N']
  8.     ) a
  9.     left join read_csv(
  10.         'e:/data/data_set/stock/stock_base.csv',
  11.         auto_detect = true,
  12.         nullstr = ['\\N']
  13.     ) b ON a.ts_code = b.ts_code
  14.     left join read_csv(
  15.         'e:/data/data_set/stock/stock_company.csv',
  16.         auto_detect = true,
  17.         nullstr = ['\\N']
  18.         ) c
  19.     ON a.ts_code = c.ts_code
  20. WHERE a.trade_date = DATE '2020-05-07' AND a.close>a.open
  21. GROUP BY c.exchange,b.industry ORDER BY up DESC;
复制代码
10.webp

 
结果说明
以上例子都是使用DuckDB直接查询CSV文件。同时也能直接查询parquet文件。读取Excel文件需要安装相应的扩展。
因为测试的机器是机械硬盘,所以效果很明显,如果是固态硬盘,那么在mysql能触发索引的情况下,两者的差距有所缩小。
如果将文件内容创建好物化视图,那么查询速度能更快一个量级。
例如:
  1. -- 创建物化视图
  2. create table view_stock_daily as select * from 'e:/data/data_set/stock/stock_daily.csv';
  3. -- 查询物化视图
  4. select * from view_stock_daily
复制代码
当然,本文对比的是DuckDB和MySQL数据查询能力,正所谓术业有专攻,MySQL的OLTP能力一直是开源界的TOP队列里的。
DuckDB和MySQL比较,有点像战斗机和客机比较飞行速度。数据是真实的但也是局部的。
本文的对比逻辑仅仅是文章介绍DuckDB能力的一个抓点。让读者能在一个标准认知的场景里清晰地理解DuckDB的能力。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册