You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何保存以整数三元组为键的大型Python字典?

可选方案推荐

针对你的只读查找场景(50万条整数三元组键+500长度整数列表值),除了pickle之外,推荐以下几种高效方案:

1. 自定义二进制格式

完全手动控制序列化/反序列化逻辑,无额外格式开销,读取速度最快,适合对性能有极致要求的场景。

实现思路:

  • 按固定字节顺序,将每个三元组键的3个整数、值列表的500个整数写入文件
  • 读取时直接按块读取二进制数据,还原后构建查找字典

代码示例:

import struct

# 写入数据
def save_dict_to_bin(my_dict, filename):
    # 每条数据大小:(3个键整数 + 500个值整数) * 4字节/整数 = 2012字节
    with open(filename, 'wb') as f:
        # 先写入总条数
        f.write(struct.pack('<I', len(my_dict)))
        for key, value in my_dict.items():
            # 写入三元组键
            f.write(struct.pack('<iii', *key))
            # 写入值列表
            f.write(struct.pack('<' + 'i'*500, *value))

# 读取数据
def load_dict_from_bin(filename):
    my_dict = {}
    with open(filename, 'rb') as f:
        count = struct.unpack('<I', f.read(4))[0]
        for _ in range(count):
            key = struct.unpack('<iii', f.read(12))
            value = list(struct.unpack('<' + 'i'*500, f.read(2000)))
            my_dict[key] = value
    return my_dict

# 使用示例
save_dict_to_bin(my_dict, 'lookup_table.bin')
loaded_dict = load_dict_from_bin('lookup_table.bin')

2. NumPy 结构化数组 + 哈希映射

利用NumPy的高效数组存储特性,将键和值分别存入数组,读取后快速构建查找字典,适合纯数值型数据场景。

实现思路:

  • 将三元组键转换为结构化数组,值存入二维数组
  • 读取后通过zip快速拼接成字典

代码示例:

import numpy as np

# 写入数据
def save_dict_to_npy(my_dict, filename_prefix):
    keys = np.array(list(my_dict.keys()), dtype=[('a', int), ('b', int), ('c', int)])
    values = np.array(list(my_dict.values()), dtype=int)
    np.save(f'{filename_prefix}_keys.npy', keys)
    np.save(f'{filename_prefix}_values.npy', values)

# 读取数据
def load_dict_from_npy(filename_prefix):
    keys = np.load(f'{filename_prefix}_keys.npy')
    values = np.load(f'{filename_prefix}_values.npy')
    return {tuple(k): v.tolist() for k, v in zip(keys, values)}

# 使用示例
save_dict_to_npy(my_dict, 'lookup_table')
loaded_dict = load_dict_from_npy('lookup_table')

3. SQLite 数据库

适合需要灵活查询、不想自己处理序列化逻辑的场景,通过复合索引保证查询速度,支持单条或批量查询。

实现思路:

  • 创建包含三个键列(a,b,c)和一个值列(存储二进制序列化的列表)的表
  • 写入时批量插入数据,创建(a,b,c)复合唯一索引
  • 读取时通过SQL查询直接获取对应值

代码示例:

import sqlite3
import pickle  # 仅用于序列化单个值列表,非整个字典

def init_db(db_path):
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS lookup_table (
            a INTEGER,
            b INTEGER,
            c INTEGER,
            value BLOB,
            PRIMARY KEY (a, b, c)
        )
    ''')
    conn.commit()
    conn.close()

def save_dict_to_sqlite(my_dict, db_path):
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    data = [(k[0], k[1], k[2], pickle.dumps(v)) for k, v in my_dict.items()]
    cursor.executemany('INSERT INTO lookup_table VALUES (?, ?, ?, ?)', data)
    conn.commit()
    conn.close()

def lookup_from_sqlite(db_path, key):
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    cursor.execute('SELECT value FROM lookup_table WHERE a=? AND b=? AND c=?', key)
    result = cursor.fetchone()
    conn.close()
    return pickle.loads(result[0]) if result else None

# 使用示例
init_db('lookup.db')
save_dict_to_sqlite(my_dict, 'lookup.db')
# 查询示例
print(lookup_from_sqlite('lookup.db', (1,2,3)))

4. Apache Parquet 文件

列式存储格式,支持压缩,适合大数据量高效存储与跨语言读取的场景。

实现思路:

  • 将三元组键拆分为三个单独列,值列表拆分为500个列(或存储为数组类型)
  • 使用PyArrow写入Parquet文件,读取后转换为字典

代码示例(使用PyArrow):

import pyarrow as pa
import pyarrow.parquet as pq

def save_dict_to_parquet(my_dict, filename):
    data = {
        'a': [], 'b': [], 'c': [],
        **{f'val_{i}': [] for i in range(500)}
    }
    for (a,b,c), vals in my_dict.items():
        data['a'].append(a)
        data['b'].append(b)
        data['c'].append(c)
        for i in range(500):
            data[f'val_{i}'].append(vals[i])
    table = pa.Table.from_pydict(data)
    pq.write_table(table, filename)

def load_dict_from_parquet(filename):
    table = pq.read_table(filename)
    df = table.to_pandas()
    my_dict = {}
    for _, row in df.iterrows():
        key = (row['a'], row['b'], row['c'])
        value = [row[f'val_{i}'] for i in range(500)]
        my_dict[key] = value
    return my_dict

# 使用示例
save_dict_to_parquet(my_dict, 'lookup_table.parquet')
loaded_dict = load_dict_from_parquet('lookup_table.parquet')

方案选择建议

  • 追求极致读取速度:选自定义二进制格式或NumPy方案
  • 需要灵活查询/多语言支持:选SQLite或Parquet
  • 希望代码简洁且性能均衡:选NumPy方案

内容的提问来源于stack exchange,提问作者Simd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 22:35:15