"""VPS 端:从 dbbardata 按 id 范围导出增量到独立 sqlite 文件。 设计要点: - 纯 sqlite3 标准库,零第三方依赖。 - 只读主库(mode=ro),不干扰 VPS 生产写入。 - 用 id(INTEGER PRIMARY KEY = rowid)作增量键:有索引,WHERE id>? 飞快, 不会像 WHERE datetime>=? 那样全表扫(datetime 无单列索引)。 - dbbardata 由 schtask 追加写入,id 递增;NAS 记录上次同步的 max_id 作下次起点。 - CREATE TABLE AS SELECT 一句导出(不含 id 列,NAS 副本 AUTOINCREMENT 自生成)。 用法: 查当前 max id: python export_increment.py --db PATH --max-id 导出 id>since: python export_increment.py --db PATH --out inc.db --id-start SINCE [--id-end END] (首次全量分片:--id-start 0 --id-end 10000000,再 10000000-20000000...) """ import argparse import os import sqlite3 COLS = ("symbol,exchange,datetime,interval,volume,turnover,open_interest," "open_price,high_price,low_price,close_price") def main(): ap = argparse.ArgumentParser(description="按 id 导出 dbbardata 增量到独立 sqlite") ap.add_argument("--db", required=True, help="源 quant_trading.db 路径") ap.add_argument("--out", help="输出增量 sqlite 路径") ap.add_argument("--id-start", type=int, default=0, help="导出 id>id_start(默认0)") ap.add_argument("--id-end", type=int, help="导出 id<=id_end(不传=全部剩余)") ap.add_argument("--max-id", action="store_true", help="只打印 MAX(id) 不导出") args = ap.parse_args() conn = sqlite3.connect("file:%s?mode=ro" % args.db, uri=True) cur = conn.cursor() if args.max_id: print("MAX_ID=%d" % cur.execute("SELECT MAX(id) FROM dbbardata").fetchone()[0]) return if not args.out: ap.error("--out required (or use --max-id)") if os.path.exists(args.out): os.remove(args.out) cur.execute("ATTACH DATABASE ? AS inc", (args.out,)) where = "id>?" params = [args.id_start] if args.id_end is not None: where += " AND id<=?" params.append(args.id_end) cur.execute( "CREATE TABLE inc.dbbardata AS " "SELECT %s FROM dbbardata WHERE %s" % (COLS, where), params) n = cur.execute("SELECT COUNT(*) FROM inc.dbbardata").fetchone()[0] # 导出范围的 max id(从源库查,rowid 快),供 NAS 记为下次起点 max_exported = cur.execute( "SELECT MAX(id) FROM dbbardata WHERE %s" % where, params).fetchone()[0] conn.commit() conn.close() size_mb = os.path.getsize(args.out) / 1048576.0 print("EXPORTED rows=%d max_id=%d sizeMB=%.1f -> %s" % (n, max_exported if max_exported else 0, size_mb, args.out)) if __name__ == "__main__": main()