LOADING

缓存加载中...

SIGMOD2026

2025/8/29 论文

 

SIGMOD 2026

这片文章记录sigmod2026的实验心路。为了防止不必要的麻烦,写一写踩坑、心得,细节只有只言片语。

主要研究内容:用大模型进行索引优化。

prepare

首先比较了启发式算法和学习式算法。

根据各种实验+调研,得出几个结论:

  1. 索引性能的优化的效果:启发式>学习式(离线)>学习式(在线)

  2. 推荐索引的选择时间,如果不算训练时间,学习式比启发式快很多。

  3. 上述比较均是在非常复杂的查询场景下,即多表、嵌套、聚合函数等,DB的snapshot也非常大。在简单的SQL上,因为可供选择的索引组合数量很少,优化空间小,启发式方法表现好,学习式方法没什么意义。

  4. 现有学习型方法不能很好的进行查询的嵌入,以及更加meta的信息的提取。现有的encode方法都比较朴素。

综合3.4.,现有学习型方法只在JoinOrderBenchmark(专门用来测试查询优化器的)表现良好,TPCH/TPCDS上有点拉胯。在事务场景(CRUD)下甚至会负优化(维护索引开销大于索引带来的查询优化)。

  1. 现有数据集严重不足,大模型微调产生的提升太小。

我们需要的:尽可能复杂的查询。同时,将多个查询装载为一个workload,对一个workload(一批查询)推荐一组索引。

大规模数据集的收集,和生成workload-index监督数据,是难点。

model

8.29

我们重新设计了开源LLM的架构,并进行微调。

首先我们进行SFT的测试。不得不说llama factory真是个好用的框架。

参数比较复杂,过几天总结记录一下。

9.4

学长修复了检查点保存的问题。今天进行训练和测试的熟悉。

因为有现有的模型,首先进行SFT。

preliminary:lmf hook

hookSystem篇。

nohup

nohup 命令可以把程序挂在后台。
记得做好输出。

MMConfig

--mm:多模态布尔开关。
--mm-efs:指定嵌入文件路径。
--mm-flm:冻结语言模型布尔开关。
--mm-pt:训练多模态布尔开关。
--mm-pckpt:多模态投影层的检查点路径。

SFT

SFT必须开启多模态。冻结语言模型,训练投影层

投影层是个两层神经网络(大约1m参数),用于将768维列嵌入映射到3584维语言模型空间

我进行SFT训练的配置。

torchrun --nporc_pernode=1 script/train.py useless.workload config/sft-projector.yaml \
--mm \
--mm-embedding-files data/* #这里是多模态表示列嵌入的文件,格式为safetensor,safetensor下面解析。\
--mm-projector-trainable \
--mm-flm #freeze language model  \
--sft #这条在sft的配置文件中写了。但我觉得不使用llama-factory可能会解析不到。 \  
每个checkpoint保存的内容的复用:

可以直接在--mm-pckpt中复用model的safetensor

safetensor

safetensor在本项目中是使用TAPAS/TaBert通过嵌入要做推荐的表格生成出来的。

结构是:键(数据库.表.列):768维嵌入向量。也就是每一列有一个768维嵌入。

RLHF

多模态交叉实验时,batch_size和梯度累计都开1依然oom……实验室算力紧张,算鸟。

SWIRL

继续做上游适配。

9.8

今天的任务,修改workload接口。

现有workload_generator的接口:

Class Workload:
    queries
    budget
    description

其中,queries是Query对象的list.

从Query到workload中有workload_from_tuple(tuples)的中间过程,workload其实是在这里生成的。
其中tuples是包含两个元组(查询类tuple,频率分布tuple)的列表或者集合。

这个函数通过组合query_class,query_text,freq生成workload.

要输入的workload类型中的key:

  • “id”(如果没有则自增,最后的查找可能比较麻烦?根据id转换回query内容。),
  • “query”查询本身
  • “frequency”频率
    其他的信息不解析。

根据config中的workload size作为步长,在json中采样。

对齐大模型输入。

TODO:

  • 继续数据准备:26个数据集上的索引。单个查询对应的最优索引,无论如何先作为标签推荐出来,跑通大模型。
  • 大模型还依赖:数据分布信息,依赖编码操作。与数据独立。在PRICE上做embedding。
  • 调整细节问题:prompt。
  • 多查询mm微调。

一,prompt处理。二,标签(index)。

9.9

要弄清楚的问题:
SWIRL的存储消耗是怎么计算的?
对齐自己输入的workload与SWIRL中的大小。

已经对齐了SWIRL的输入端。
在config中增加了两个参数:

ExternalWorkload:布尔类型,决定是否使用外部workload.
WorkloadPath:外部workload的路径。

现在要考虑的对齐:

  • workload的size。之前的链路是,有查询类,然后config中固定workload大小,按大小采样Query。现在如果固定workload size,因为外部输入的workload size是不固定的。
    • 要么用config中的workload size,这样,就先洗混workload中的Query,按输入的size采样。
    • 要么将外部输入,直接按json的格式拿出来。
  • label标签的添加。
    • 每个workload一个label.

9.10

SWIRL的workload嵌入问题依然没解决。因为外部输入的workload大小不超过15,那么直接将feature表征宽度都按15来,不足的补0可不可行。

同时对PRICE中的表格数据用TAPAS进行嵌入。

执行column_embedding的脚本:

python scripts/gen/column_embedding/{dbname}.py --db {dbname} --output /data/baiyutao/PRICEembedding/{dbname}.safetensor --sample_count 100

在此之前,我们需要数据库的schema。已经有另一个脚本,支持直接从pg的数据库得出。

python scripts/gen/schemas.py --add-init --db [dbname]

9.11

虽然论文中说SWIRL可以通过补0或者语义压缩等方法实现workload大小的对齐,但是代码中确实没有实现这一点。

今天的todo:

  • SWIRL实现训练workload的对齐。
  • index eab用启发式算法做多查询workload上的index标签生成。
  • 针对多查询的workload上进行查询级别的嵌入。
  1. SWIRL的padding实现

一般来说是用动态填充注意力掩码实现
尝试了一下,性能估计器会出问题。

  1. indexEAB启发式打标签
    跑通了。命令:
      python heu_run.py
    --res_save /index_advisor_selector/index_selection/heu_res.json \
    --process --overhead \
    --sel_params parameters \
    --exp_conf_file /configuration_loader/index_advisor/heu_run_conf/extend_config.json \
    --constraint storage --budget_MB 3000  \
    --cand_gen permutation --est_model optimizer \
    --work_file /workload_generator/template_based/tpch_work_temp_multi.json\
    --db_conf_file /configuration_loader/database/db_con.conf\
    --schema_file /configuration_loader/database/schema_tpch.json\

9.12

今天生成PRICE中的多query workload标签,并嵌入到自己的大模型里。
好多。顺便验证了SWIRL使用生成的workload也能保存到workload+label的标签中。

9.13

正式开始大规模微调。

流程:

  1. 用带标签的数据训练投影层,即SFT投影层,可以在多个数据库上联合进行。寻找合适的超参数,确保训练充分,最后的loss值应该降到0.x甚至0.0x,让训练是过拟合的,从而可以在训练的ckpt中找到最优。同时,投影层的训练要求更高的学习率,1e-3是经过验证的不错的学习率,epoch时间尝试长一些,待验证。

    CUDA_VISIBLE_DEVICES=2 python scripts/sft_projector.py workloads/index_eab/10q/job+tpch.2000w.5-15q.workload.labeled.json --eval-set-percent 0.1 --output-dir saves/sft_projector_both --mm --mm2 --mm-flm --mm-embedding-files embeddings/imdb.tapas.1000.safetensors embeddings/tpch1g.tapas.10000.safetensors --mm2-embedding-files workloads/index_eab/job_1500.safetensors workloads/index_eab/tpch_2000.safetensors --mm-projector-trainable --mm2-projector-trainable --epochs 30 --batch-size 4 --learning-rate 1e-3 --debug config/sft-projector.yaml  > ~/output_qwen_projector_both.txt 2>&1 &
  2. 联合训练投影层与映射层,要将投影层参数穿进去,进行sft。这里用PRICE数据集跑一下,当作预训练流程,在足够多的数据集上预训练之后,保证在新数据集上有效果而不用进一步微调。

CUDA_VISIBLE_DEVICES=3  python scripts/sft_projector.py workloads/index_eab/10q/job+tpch.2000w.5-15q.workload.labeled.json --eval-set-percent 0.1 --output-dir saves/sft_full --mm --mm2 --mm-embedding-files embeddings/imdb.tapas.1000.safetensors embeddings/tpch1g.tapas.10000.safetensors --mm2-embedding-files workloads/index_eab/job_1500.safetensors workloads/index_eab/tpch_2000.safetensors --mm-projector-trainable --mm2-projector-trainable --mm-pckpt saves/sft_projector_both/checkpoint-2000/projector.safetensors --mm2-pckpt saves/sft_projector_both/checkpoint-2000/projector.safetensors --epochs 6 --batch-size 4 --learning-rate 1e-4 --debug config/lib-sft.yaml > ~/output_full_sft0.txt 2>&1 &
  1. eval阶段,PRICE上训完之后,看看在TPCH上的效果。效果不好的话:多用几个数据集/变化查询数量和复杂度。
python scripts/eval.py workloads/index_eab/10q/tpch.2000.1000w.5-15q.workload.json eval/res1.json --mm --mm2 --mm-embedding-files embeddings/tpch.tapas.1000.safetensors --mm2-embedding-files workloads/index_eab/tpch_2000.safetensors --ckpt 2300:2400:100 --gpu 2  -b 4 --db tpch1g --dbuser wuyinjun --dbpswd "" --debug config/eval-qwen.yaml
  1. 后文。
    提示词调整:现在的prompt还有荣誉,列向量中不应该放进去所有列,而是应该收集关键列,比如join/predicate中的。我们要从workload中收集关键列。
    对列向量本身的嵌入做改进,现在是单个sample100,依照多模态的经验,可以像卷积神经网络那样,尝试多次采样。即列嵌入时生成多个embedding,多次采样。

TODO
首先,我要从PRICE中生成:多批,每批1000个workload,每个大小为10,frequency先固定,用extend或者SWIRL打标签。

尝试用SWIRL打标签:训练8k个,打500个,慢成史了,估算了一下要跑80h,紧急停止了。
尝试用extend:首先要改成IndexEAB能接受的数据,然后做一些偏移。IndexEAB一开始的三种workload:1.template:用模板,只改参数;2.perturb:修改predicate的值,添加额外列。3.random:随机生成select-proj-join查询。

9.14

又整理了一下pipeline:

PRICE中的初始SQL负载: 准备3个数据集上的测试一下:Baseball,Basketball,chembl。
每个各1k个workload,workload大小均为10个。

先修改一下SWIRL的逻辑,使得生成结果可以直接对齐sft.这一步与indexEAB无关。(已完成)

->index_advisor中的脚本script/gen/workloads.py,add_labels.py,merge.py可以将sql生成sft可用的workload文件。同时,这里的sql要进行embedding.
workload.py直接提取出基础workload结构
add_labels为每个workload加上labels,这里要用到index_eab的推荐结果
merge.py将多个workload文件合并成一个
这里labels的生成,要用extend.

SWIRL的生成方法:直接生成出sft可用的格式。
extend则需上面的脚本。

尝试用extend生成。首先要把PRICE数据集分割成id+sql+freq的形式以供算法使用。
先把freq都设为1。
几个重要的参数:

--cand_gen

->进行sft