利用DeepSeek和qwen 3.5辅助生成SQL优化方法幻灯片视频

一开始想用qwen 3.5来做,结果做成的是图形格式的PDF, 而且不能输出生成幻灯片的脚本,不太满意,于是让DeepSeek再做一版。

提示如下, 提纲是qwen输出的。

生成SQL优化方法介绍幻灯片。

优化维度:1. 索引优化基础与使用原则(合理创建B+树索引|避免在索引列上使用函数或计算);2. 查询语句写法规范与技巧(优先使用WHERE而非HAVING|避免SELECT *|善用LIMIT分页);3. 表结构设计基础规范(遵循三范式但适度反范式|合理选择数据类型|主键必设且用INT/UUID);4. 使用EXPLAIN分析执行计划(关注type、rows、key、Extra字段|识别ALL/Using filesort等警告);5. 避免全表扫描与常见性能陷阱(NULL值导致索引失效|LIKE '%abc'无法走索引|JOIN字段未建索引),最终凝练为"少查、快连、精索、常析、避坑"五大实战原则。

先输出第一个专题:索引。数据库中B+树索引的原理、创建、失效规避与实践验证方法;涵盖合理构建复合索引(如idx_user_status_time)、严防索引失效场景(禁止函数包裹、LIKE '%xxx'、隐式转换等)、通过EXPLAIN ANALYZE监控验证效果三大策略;深入解析索引底层结构、写法合规性对执行计划的影响,突出"索引要建得准、用得对、管得勤"。

用postgresql数据库举例,输出生成幻灯片的python代码。

首先根据代码中的提示安装

复制代码
pip install manim

Installing collected packages: svgelements, pyglm, pydub, glcontext, watchdog, srt, soupsieve, skia-pathops, screeninfo, pyglet, pycairo, networkx, moderngl, mapbox-earcut, manimpango, isosurfaces, decorator, av, audioop-lts, moderngl-window, cloup, beautifulsoup4, manim
Successfully installed audioop-lts-0.2.2 av-16.1.0 beautifulsoup4-4.14.3 cloup-3.0.8 decorator-5.2.1 glcontext-3.0.0 isosurfaces-0.1.2 manim-0.19.2 manimpango-0.6.1 mapbox-earcut-2.0.0 moderngl-5.12.0 moderngl-window-3.1.1 networkx-3.6.1 pycairo-1.29.0 pydub-0.25.1 pyglet-2.1.13 pyglm-2.8.3 screeninfo-0.8.1 skia-pathops-0.9.2 soupsieve-2.8.3 srt-3.5.3 svgelements-1.9.6 watchdog-6.0.0

pip install manim-slides

Installing collected packages: XlsxWriter, rtoml, qtpy, MarkupSafe, python-pptx, jinja2, click-default-group, pydantic-extra-types, manim-slides
Successfully installed MarkupSafe-3.0.3 XlsxWriter-3.2.9 click-default-group-1.2.4 jinja2-3.1.6 manim-slides-5.5.4 pydantic-extra-types-2.11.0 python-pptx-1.0.2 qtpy-2.4.3 rtoml-0.13.0

执行命令行, 他生成的脚本有错,

复制代码
manim -pql index_slides.py IndexOptimization
C:\Users\lt\AppData\Local\Programs\Python\Python313\Lib\site-packages\pydub\utils.py:170: RuntimeWarning: Couldn't find ffmpeg or avconv - defaulting to ffmpeg, but may not work
  warn("Couldn't find ffmpeg or avconv - defaulting to ffmpeg, but may not work", RuntimeWarning)
...
TypeError: Code.__init__() got an unexpected keyword argument 'code'
TypeError: Code.__init__() got an unexpected keyword argument 'insert_line_no'

把错误信息提供给他,他把code改成text后仍然不对,自己到manim 官方文档页面查询,得知了正确的参数名是code_string,同样的,insert_line_no应该是add_line_numbers,并且不存在font_size参数,都改正后的脚本如下:

python 复制代码
from manim import *
from manim_slides import Slide

# 配置中文字体,请根据系统环境调整
config.tex_template.add_to_preamble(r"\usepackage{ctex}")
config.tex_template.add_to_preamble(r"\usepackage{xcolor}")

class IndexOptimization(Slide):
    """PostgreSQL 索引优化专题幻灯片 - 索引篇"""
    def construct(self):
        # ---------- 标题页 ----------
        title = Text("PostgreSQL 索引优化实战", font_size=48, color=BLUE)
        subtitle = Text("第一专题:索引", font_size=36, color=GRAY)
        authors = Text("少查·快连·精索·常析·避坑", font_size=28, color=GREEN)
        VGroup(title, subtitle, authors).arrange(DOWN, buff=0.5)
        self.play(Write(title))
        self.play(FadeIn(subtitle, shift=UP))
        self.play(FadeIn(authors, shift=UP))
        self.wait(1)
        self.next_slide()  # 进入下一页

        # 清除当前画面
        self.clear()

        # ---------- 1. B+树索引原理 ----------
        principle_title = Text("1. B+树索引原理", font_size=40, color=YELLOW).to_edge(UP)
        self.play(Write(principle_title))

        # 绘制简单的B+树结构
        root = Circle(radius=0.3, color=BLUE).shift(UP*3)
        root_label = Text("根页", font_size=20).move_to(root)
        leaf1 = Circle(radius=0.3, color=GREEN).shift(LEFT*3)
        leaf2 = Circle(radius=0.3, color=GREEN).shift(LEFT*1)
        leaf3 = Circle(radius=0.3, color=GREEN).shift(RIGHT*1)
        leaf4 = Circle(radius=0.3, color=GREEN).shift(RIGHT*3)
        leaf_label1 = Text("数据页1", font_size=16).next_to(leaf1, DOWN)
        leaf_label2 = Text("数据页2", font_size=16).next_to(leaf2, DOWN)
        leaf_label3 = Text("数据页3", font_size=16).next_to(leaf3, DOWN)
        leaf_label4 = Text("数据页4", font_size=16).next_to(leaf4, DOWN)

        arrows = VGroup(
            Arrow(root.get_bottom(), leaf1.get_top(), buff=0.1),
            Arrow(root.get_bottom(), leaf2.get_top(), buff=0.1),
            Arrow(root.get_bottom(), leaf3.get_top(), buff=0.1),
            Arrow(root.get_bottom(), leaf4.get_top(), buff=0.1),
        )

        tree = VGroup(root, root_label, leaf1, leaf2, leaf3, leaf4,
                      leaf_label1, leaf_label2, leaf_label3, leaf_label4, arrows)
        tree.scale(0.8).shift(DOWN*1.5)

        self.play(GrowFromCenter(root), Write(root_label))
        self.play(*[GrowFromCenter(leaf) for leaf in [leaf1, leaf2, leaf3, leaf4]])
        self.play(*[Write(lab) for lab in [leaf_label1, leaf_label2, leaf_label3, leaf_label4]])
        self.play(*[GrowArrow(arr) for arr in arrows])

        # 添加解释文字
        explain = Text(
            "B+树特点:\n- 所有数据在叶子节点\n- 叶子间双向链表连接\n- 高度平衡,3~4层即可支撑百万记录",
            font_size=24, color=GRAY, line_spacing=1.2
        ).to_edge(RIGHT).shift(UP)
        self.play(Write(explain))
        self.wait(2)
        self.next_slide()

        # ---------- 2. 索引创建规范 ----------
        self.clear()
        create_title = Text("2. 索引创建规范", font_size=40, color=YELLOW).to_edge(UP)
        self.play(Write(create_title))

        # 表结构示例
        table_code = Code(
            code_string='''
CREATE TABLE users (
    id BIGSERIAL PRIMARY KEY,
    status INT NOT NULL,
    created_at TIMESTAMP NOT NULL,
    email VARCHAR(255)
);
            ''',
            language="sql",
            #font_size=24,
            background="window",
            add_line_numbers=False
        ).shift(LEFT*3).scale(0.8)

        # 复合索引推荐
        idx_code = Code(
            code_string='''
-- 推荐复合索引
CREATE INDEX idx_user_status_time 
ON users(status, created_at);

-- 适合查询:
SELECT * FROM users
WHERE status = 1 
ORDER BY created_at DESC;
            ''',
            language="sql",
            #font_size=24,
            background="window",
            add_line_numbers=False
        ).next_to(table_code, DOWN, buff=0.5)

        self.play(FadeIn(table_code, shift=UP))
        self.play(FadeIn(idx_code, shift=UP))

        # 附加说明
        note = Text(
            "原则:\n- 等值条件列放前面\n- 排序/范围列放后面\n- 索引列不宜过多(5列内)",
            font_size=24, color=BLUE, line_spacing=1.5
        ).to_edge(RIGHT)
        self.play(Write(note))
        self.wait(2)
        self.next_slide()

        # ---------- 3. 索引失效场景 ----------
        self.clear()
        invalid_title = Text("3. 严防索引失效场景", font_size=40, color=YELLOW).to_edge(UP)
        self.play(Write(invalid_title))

        # 用表格展示失效场景
        table = Table(
            [["函数包裹", "WHERE func(col) = value"],
             ["LIKE '%xxx'", "WHERE name LIKE '%abc'"],
             ["隐式转换", "WHERE phone = 123456 (phone是varchar)"],
             ["复合索引跳跃列", "跳过前导列直接查created_at"]],
            col_labels=[Text("失效场景"), Text("错误示例")],
            include_outer_lines=True,
            line_config={"stroke_width": 1, "color": GRAY},
            element_to_mobject_config={"font_size": 20}
        ).scale(0.7).shift(UP*1)

        self.play(Create(table))

        # 添加红色警示
        warning = Text(
            "后果: 全表扫描(ALL) | 性能急剧下降",
            font_size=28, color=RED
        ).shift(DOWN*2)
        self.play(Write(warning))
        self.wait(2)
        self.next_slide()

        # ---------- 4. 通过EXPLAIN ANALYZE验证 ----------
        self.clear()
        explain_title = Text("4. EXPLAIN ANALYZE 验证效果", font_size=40, color=YELLOW).to_edge(UP)
        self.play(Write(explain_title))

        # 展示执行计划对比
        plan_good = Code(
            code_string='''-- 正确使用索引的计划
=> EXPLAIN ANALYZE SELECT * FROM users 
   WHERE status = 1 ORDER BY created_at;
--------------------------------------------------------------------
 Index Scan using idx_user_status_time on users  
   (cost=0.15..8.17 rows=1 width=8) 
   (actual time=0.024..0.025 rows=1 loops=1)
 Planning Time: 0.123 ms
 Execution Time: 0.045 ms''',
            language="sql",
            #font_size=20,
            background="window",
            add_line_numbers=False
        ).shift(UP*0.5).scale(0.7)

        plan_bad = Code(
            code_string='''-- 函数包裹导致索引失效
=> EXPLAIN ANALYZE SELECT * FROM users 
   WHERE EXTRACT(YEAR FROM created_at) = 2023;
--------------------------------------------------------------------
 Seq Scan on users  
   (cost=0.00..22.75 rows=4 width=8) 
   (actual time=0.078..0.139 rows=4 loops=1)
 Planning Time: 0.234 ms
 Execution Time: 0.176 ms''',
            language="sql",
            #font_size=20,
            background="window",
            add_line_numbers=False
        ).next_to(plan_good, DOWN, buff=0.3).scale(0.7)

        self.play(FadeIn(plan_good, shift=LEFT))
        self.play(FadeIn(plan_bad, shift=RIGHT))

        # 高亮关键指标
        circle_good = Circle(color=GREEN, radius=0.5).move_to(plan_good.get_center()+DOWN*0.5)
        circle_bad = Circle(color=RED, radius=0.5).move_to(plan_bad.get_center()+DOWN*0.5)
        self.play(Create(circle_good), Create(circle_bad))

        note = Text("关注: type(Index Scan vs Seq Scan), actual time, rows", font_size=24).to_edge(DOWN)
        self.play(Write(note))
        self.wait(2)
        self.next_slide()

        # ---------- 5. 总结与实战原则 ----------
        self.clear()
        summary_title = Text("索引优化五大原则", font_size=44, color=YELLOW).to_edge(UP)
        self.play(Write(summary_title))

        principles = VGroup(
            Text("1️⃣ 建得准: 根据查询模式设计复合索引 (如idx_user_status_time)", font_size=28),
            Text("2️⃣ 用得对: 避免函数、隐式转换、前导模糊", font_size=28),
            Text("3️⃣ 管得勤: 定期用EXPLAIN ANALYZE验证, 删除冗余索引", font_size=28),
            Text("4️⃣ 覆盖索引: 考虑包含列(INCLUDE)减少回表", font_size=28),
            Text("5️⃣ 监控: pg_stat_user_indexes 查看使用率", font_size=28),
        ).arrange(DOWN, aligned_edge=LEFT, buff=0.3).shift(UP*0.5)

        for p in principles:
            self.play(Write(p, lag_ratio=0.1))
            self.wait(0.3)

        footer = Text(
            "下一专题预告: 查询语句写法规范与技巧",
            font_size=24, color=GRAY
        ).to_edge(DOWN)
        self.play(Write(footer))
        self.wait(3)


# 如果要生成视频幻灯片,需安装 manim 和 manim-slides,然后运行:
# manim -pql index_slides.py IndexOptimization
# manim-slides indexoptimization

另外,下载ffmpeg, 将压缩包解压到C:\d\ffmpeg\bin,添加到PATH环境变量。

复制代码
wget https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.7z

Saving to: 'ffmpeg-release-essentials.7z'

set path=%path%;C:\d\ffmpeg\bin

再次执行就成功生成了mp4格式的幻灯片。

复制代码
                    INFO     Rendered IndexOptimization                                                     scene.py:278
                             Played 39 animations
[02/17/26 17:19:55] INFO     Previewed File at:                                                          file_ops.py:237
                             'C:\d\media\videos\index_slides\480p15\IndexOptimization.mp4'
[02/17/26 17:19:58] INFO     Generated 6 slides to 'C:\d\slides\files\IndexOptimization'                     base.py:599
[02/17/26 17:19:58] INFO     Generated 6 slides to 'C:\d\slides\files\IndexOptimization'                     base.py:599
                    INFO     Slide 'IndexOptimization' configuration written in                              base.py:611
                             'C:\d\slides\IndexOptimization.json'
                    INFO     Slide 'IndexOptimization' configuration written in                              base.py:611
                             'C:\d\slides\IndexOptimization.json'

第二个命令行还是报错,看提示是缺少qt包,暂时不管了。

复制代码
manim-slides indexoptimization
Traceback (most recent call last):
...
qtpy.QtBindingsNotFoundError: No Qt bindings could be found
相关推荐
_千思_2 小时前
【小白说】数据库系统概念 4
数据库
专注&突破2 小时前
DeepAgents 的 Backend详解
数据库
星火开发设计2 小时前
序列式容器:list 双向链表的特性与用法
开发语言·前端·数据结构·数据库·c++·链表·list
Zzz 小生2 小时前
LangChain Messages:消息使用完全指南
数据库·windows·microsoft
yq1982043011562 小时前
基于Python爬虫原理的Pinterest视频资源获取技术解析与工具实践
爬虫·python·django·音视频
不吃鱼的猫7482 小时前
【ffplay 源码解析系列】01-开篇-ffplay整体架构与启动流程
c++·架构·ffmpeg·音视频
寂寞旅行11 小时前
向量数据库Milvus的使用
数据库·milvus
闻哥11 小时前
Redis事务详解
java·数据库·spring boot·redis·缓存·面试
道亦无名12 小时前
aiPbMgrSendAck
java·网络·数据库