news 2026/10/2 5:04:52

学生学籍管理系统SQL Server完整设计:从E-R图到触发器实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
学生学籍管理系统SQL Server完整设计:从E-R图到触发器实战

简介:数据库设计是管理信息系统开发的基础环节。以E-R图梳理实体关系后,通过外键依赖顺序完成九张核心表的建表SQL,并结合索引、视图、存储过程与触发器封装业务逻辑,是SQL Server环境下学生学籍管理系统的典型实践。这样的分层设计既能保证选课成绩、学院专业班级等数据的一致性,也能支持按学院、专业、班级、课程统计的查询场景。围绕这份开源课程设计文档,拆解可复现的建库建表语句,并给出常见运行错误(外键报错、触发器递归、avg取错列)的排查方法,帮助开发者快速用SQL Server完成功能完整的学籍成绩管理模块。

1. 学生学籍管理系统:一份 doc 文档里装着的完整 SQL Server 数据库设计

这份资源打动我的地方在于:封面写的是「学生成绩管理管理系统」,打开看内容却是一份相当完整的学籍+成绩一体化数据库课程设计。需求分析、E-R 图、九张表的建表 SQL、三个索引、十一个视图、五个存储过程、十三个触发器,全在一份 .doc 文档里,而且不是纸面设计——建库、建表、索引、视图、存储过程、触发器每一段都给了可直接执行的 SQL。对正在做数据库课程设计、或者想找个现成业务场景练 SQL Server 的人,这份 doc 几乎就是照着抄都能交作业的底稿。本文从数据结构拆起,讲清楚每张表为什么这么建,再给可复现的 SQL 和五个我实际跑出来的坑。

2. 先理关系再建表:从 E-R 图到九张表的完整拆解

2.1 实体与关系:一对多、多对多分别落在哪

这份设计最值得参考的是概念结构部分,它把学籍管理拆成了七个核心实体:学院、专业、年级、班级、学生、课程、教师,外加一个教研室。实体之间的关系在原文里描述得很直白,落成关系模式之前我习惯先列表格把基数钉死,否则后面外键会乱。

关系基数落表方式
学院 - 专业1:n专业表 major 存 collegename 外键
专业 - 年级m:n年级表 grades 同时挂专业与学院
专业 - 班级1:n班级表 classes 存 majorname
班级 - 学生1:n学生表 student 存 class
学生 - 课程m:n选课成绩表 selectcourse,成绩做属性
学院 - 教师1:n教师表 teachers 存 collegename
教师 - 课程m:n教师任课表 teachercourse

注意「专业 - 年级」在这里建模成多对多,实际项目里我更倾向于把年级挂在专业下面做一对多,因为一个专业多个年级、一个年级横跨多个专业的情况很少见。但课程设计按原文这个模型也不算错,grades 表用 grade 做联合主键之一,后面建表时能自洽就行。

2.2 关系模式转换:主键与复合主键怎么定

逻辑结构设计阶段,原文把概念模型转成了九个关系模式,这是整份文档里含金量最高的一段。逐条列出来是这样的:

  • 学生信息表 student:主键 sno,外键学院、专业、年级、班级
  • 课程数据表 course:主键 cno,外键学院
  • 选课成绩表 selectcourse:复合主键(sno, cno),外键学号、课程号、教师工号
  • 教师数据表 teachers:主键 teacherID,外键学院、教研室
  • 学院表 college:主键 collegename
  • 专业表 major:主键 majorname,外键学院
  • 年级表 grades:主键 grade,外键学院、专业
  • 班级表 classes:主键 class,外键年级、学院、专业
  • 教研室表 depart:主键 department,外键学院
  • 教师任课表 teachercourse:复合主键(cno, teacherID)

这里有个值得多说一句的设计点:selectcourse 用了(sno, cno)做复合主键,这保证了同一个学生同一门课只能有一条成绩记录,符合业务直觉。但同时把 teacherID 也塞进这张表,意味着如果一个老师教多个班的同一门课、学生按班分开选,成绩记录就会变成多条,复合主键就得扩成(sno, cno, teacherID)。真实系统里这是常见的需求变体,照着原资源做课设没问题,如果做毕设加分项,建议在主键里把 teacherID 考虑进去。

2.3 物理结构:每个字段的类型选择都有讲究

物理结构部分把每张表的字段名、类型、长度、主外键都定了。我挑几个关键的字段设计说明为什么是这么选的:

  • 学号 sno 用 char(10) 而不是 varchar:学号定长,避免存储碎片,而且支持前导零。
  • 年龄 sage 用 smallint:范围够用(最大 32767),比 int 省一半空间。
  • 性别 sex 用 char(2):就存一个「男/女」,char 定长效率高。
  • 电话 tel 用 varchar(16):允许为空,只有长度上限,不定长存储。
  • 成绩 score 用 int:原文没用 decimal,做平均成绩计算时会有精度损失,这个后面讲存储过程再展开。

字段类型这种细节,答辩时老师最喜欢问「为什么这里用 char 不用 varchar」,能答出上面这套说辞,基本就能证明你不是纯抄的。

3. 把设计文档变成可执行 SQL:建库、建表与依赖顺序

3.1 建库语句:路径、初始大小和增长策略

原文给的第一段可执行 SQL 是建库,我的建议是先检查目标路径存在,再跑下面的语句:

create database studentmanagesystem on primary( name='studentmanagement', filename='D:\DATA\studentmanagesystem.mdf', size=3, maxsize=unlimited, filegrowth=1 ) log on( name='studentmanagesystem_log', filename='D:\DATA\studentmanagesystem_log.ldf', size=1, maxsize=2, filegrowth=10% )

这段参数里有三个坑值得说明。size=3 表示初始 3MB,注意单位是 MB 而不是页,SQL Server 2005 之后这个参数默认按 MB 算。filegrowth=1 是按 1MB 增长,适合小规模课设;maxsize=unlimited 表示不设上限。日志文件 maxsize=2 是 2MB,如果后面批量插入测试数据,日志很容易撑满报 9002 错误,实操时我一般直接改成 maxsize=unlimited。

文件路径 D:\DATA 必须先创建,否则会报操作系统错误 3(文件找不到)。另外如果本机已经建过同名的库,会报「数据库已存在」,需要先 drop 或换库名。

3.2 按外键依赖顺序建表

建表要严格按依赖顺序来:先建被引用的父表,再建引用它们的子表。这个顺序我吃过亏,原来图省事从 student 开始建,直接报「FOREIGN KEY 引用了不存在的表」。正确顺序是:

college → major → grades → classes → student → course → depart → teachers → selectcourse → teachercourse

先看学院和专业这两张最基础的:

create table college ( collegename varchar(20) primary key not null, collegeID int not null ); create table major ( majorname varchar(20) primary key not null, majorID int not null, collegename varchar(20) not null, foreign key (collegename) references college (collegename) );

这里主键用的是学院名称字符串而不是编号,在课程设计里常见,好处是查询时不用关联就能看到名称;代价是如果学院改名,所有引用它的子表都要级联更新。真实生产系统一般会换成 collegeID 做代理主键。注意学院表先建,major 才能引用它。

接着是年级和班级,这两张表都引用了 college 和 major:

create table grades ( grade int not null primary key, collegename varchar(20) not null, majorname varchar(20) not null, foreign key (collegename) references college (collegename), foreign key (majorname) references major (majorname) ); create table classes ( class char(10) not null primary key, grade int not null, collegename varchar(20) not null, majorname varchar(20) not null, foreign key (collegename) references college (collegename), foreign key (majorname) references major (majorname), foreign key (grade) references grades (grade) );

grades 表把 grade 直接当主键,意味着同一年级不同专业会冲突——比如 2024 级计算机和 2024 级软件工程都要存,grade 都是 2024,主键就撞了。这是原设计的一个隐患,实际跑数据时很可能翻车。我建议把主键改成(grade, majorname)联合,或者加一个自增 ID。classes 表也同理,class 用 char(10) 存「计科2401」这类值,靠业务保证不重名。

学生表是外键最多的表,几乎把上面的父表引用了一遍:

create table student ( sno char(10) primary key not null, studentname varchar(10) not null, sex char(2), sage smallint, collegename varchar(20), majorname varchar(20), grade int, class char(10), tel varchar(16), foreign key (collegename) references college (collegename), foreign key (majorname) references major (majorname), foreign key (grade) references grades (grade), foreign key (class) references classes (class) );

九个字段挂了四个外键,这是学籍表的标准结构。注意这些外键字段在原文里都没加 not null,意味着允许学生暂时未分配班级,业务上说得通,但查询时要用左连接避免丢数据。选课成绩表 selectcourse 是另一个重点:

create table selectcourse ( sno char(10) not null, cno char(10) not null, teacherID varchar(10), score int, primary key (sno, cno), foreign key (sno) references student (sno), foreign key (cno) references course (cno), foreign key (teacherID) references teachers (teacherID) );

sno 和 cno 构成复合主键,保证一个学生一门课只有一条成绩。但这里有个隐患要提前说:course 表还没建,所以这段 SQL 必须等 course 和 teachers 建完才能执行,顺序上我习惯把 course 和 depart、teachers 插在 student 之后、selectcourse 之前。teachercourse 表是同构的复合主键结构,不再赘述。

3.3 索引:三个 nonclustered 索引怎么选列

原文建了三个索引,都是 nonclustered,语句如下:

create nonclustered index score_index on selectcourse (score desc); create nonclustered index student_sage_index on student (sage desc); create nonclustered index teachers_sage_index on teachers (sage desc);

成绩索引是合理的,成绩列是查询和排序的高频列,desc 排序配合「查最高分/排名」类语句很顺手。但给 student.sage 和 teachers.sage 建索引属于「不知道建什么就建了」的典型做法——年龄列的区分度极低,查询时优化器大概率扫全表也不用这个索引,而且每次插入学生都要维护索引,反而拖慢写入。课设阶段留着不扣分,答辩问起来就说「支撑按年龄段的统计查询」,但如果是我做设计,这两个索引我会直接删掉,把资源留给 selectcourse 的 teacherID 外键列。

4. 把业务逻辑收进数据库:视图、存储过程与触发器的实现

4.1 视图:把高频查询固化下来

原文一口气建了十一个视图,几乎覆盖了所有查询场景,清单如下:

视图名用途
student_view全部学生信息
college_major_s按学院专业查学生
class_s按班级查学生
college_course按学院查课程
selectcourse_s各班选课成绩
avg_s各班学号及平均成绩
teachers_view教师信息
depart_view教研室信息
teachercourse_view教师任课信息
c_major_view学院-专业对照

有两个视图值得细看。avg_s 是「按班级算平均成绩」的核心视图,原文写法在 SQL Server 里会直接报错,因为 group by 后面没有聚合函数,我在这给出修正写法:

create view avg_s (sno, grade, class, gavg) as select selectcourse.sno, class_s.grade, class_s.class, avg(selectcourse.score) from selectcourse, class_s where selectcourse.sno = class_s.sno group by class_s.grade, class_s.class, selectcourse.sno;

avg 函数必须和 group by 的列共存,这是 SQL 的硬规则。加个 avg(score) 之后,这个视图就能直接回答「某个班每个学生的平均分是多少」。

另一个是 c_major_view,做学院和专业的关联透视:

create view c_major_view (collegename, collegeID, majorname, majorID) as select college.collegename, college.collegeID, major.majorname, major.majorID from college, major where major.collegename = college.collegename;

这种手工写连接条件的写法是 SQL Server 2005 时代的风格,功能没问题,但现在的主流习惯是用 inner join。视图层的意义在于,前端或者报表工具直接查视图名就行,不用关心底层表结构。

4.2 存储过程:输入参数与输出参数的配合

五个存储过程分别对应:查学生成绩、查课程平均分和选课人次、查学院专业统计、查班级名单、查教师任课。参数类型分两类:输入参数用@xxx char/int传入,输出参数用@xxx output返回标量结果。先看最简单的成绩查询:

create proc scoreproc @sno char(10) as begin select student.sno, student.studentname, course.coursename, selectcourse.score, course.credit from student, course, selectcourse where student.sno = selectcourse.sno and course.cno = selectcourse.cno and student.sno = @sno end

调用方式exec scoreproc '2024001'。注意传参用字符串字面量,因为 @sno 声明为 char(10),如果传 '001' 会自动补空格,查不到数据时先检查是不是这里出了问题。

第二个存储过程是输出参数的标准范例:

create proc avgscoreproc @cname char(20), @avg int output, @count smallint output as begin select @avg = avg(selectcourse.score), @count = count(*) from course, selectcourse where course.cno = selectcourse.cno and course.coursename = @cname end

调用时要先 declare 变量再传 output:

declare @a int, @b smallint; exec avgscoreproc '数据库原理', @a output, @b output; select @a as 平均成绩, @b as 选课人次;

这里有个细节:@avg 声明为 int,但 avg(score) 的结果大概率带小数,int 会直接截断。课程设计文档里这么写不算错,但如果你是拿去做真实报表,建议把 @avg 改成 decimal(5,2),score 列也建议从 int 改成 decimal(5,2),否则 89.5 和 89.25 会被算成同一个值。另外注意原文档里写的是 avg(grade),这是错的,成绩列在 selectcourse 表里叫 score,grade 是年级字段,照抄会算出完全没意义的结果,这个坑放到避坑章节细讲。

classproc 那个存储过程是参数最多的一个,输入学院、专业、年级、班级四个参数,输出班级人数。实际调用时四个参数必须完全匹配,特别是 grade 是 int 类型,传字符串会隐式转换,SQL Server 里容易出「转换失败」的报错,建议先查 grades 表确认年级值再传。

4.3 触发器:级联删除、级联更新与数据校验

原文的触发器分三类。第一类是级联删除,删除课程时同步删除选课成绩:

create trigger ctrig on course after delete as begin delete selectcourse where cno in (select cno from deleted) end

原理是 deleted 临时表里保存了被删除的课程行,触发器通过它拿到涉及的 cno,再去选课表清理。注意原文写的是delete SC,SC 是表别名不是真实表名,SQL Server 不认识,直接报错,正确表名是 selectcourse。

第二类是级联更新。修改学生学号时,选课表里的学号要跟着变:

create trigger strigger on student after update as begin update selectcourse set sno = (select sno from inserted) where sno in (select sno from deleted) end

插入和删除临时表在这里各司其职:inserted 存新值,deleted 存旧值。这个触发器在 SQL Server 里有个隐含限制——一次 update 语句更新多行学生时,(select sno from inserted) 会返回多行导致赋值出错,真要支持批量更新得用 join 写法。课设场景只测单条更新没问题。

第三类是数据校验触发器,防止插入不存在的学号或课程号:

create trigger check_trig on selectcourse after insert as begin if exists ( select * from inserted where sno not in (select sno from student) or cno not in (select cno from course) ) rollback end

注意原文写的是not in (select sno from s),s 这个表根本不存在,正确的是 student。另外 rollback 在触发器里会撤销整个插入事务,包括触发它的那条语句。这套触发器逻辑在 SQL Server 2005 时代是标准做法,但放到 2019 之后,外键约束本身就能完成同样的校验,触发器的意义主要是演示用。

5. 避坑排查:这份文档里藏着的五个经典翻车点

5.1 建表顺序导致外键报错

现象:不从 college 开始建,先执行create table student,SQL Server 报错「FOREIGN KEY 约束引用了表 'college',该表不存在或尚未创建」。

原因:student 表四个外键分别引用 college、major、grades、classes,这四个父表还没建,引用关系无处安放。

解决:严格按 college → major → grades → classes → student 的顺序执行建表语句。如果建到一半发现顺序乱了,把已经建好的子表先 drop 再重来。我自己的习惯是先把所有建表语句写进一个 .sql 文件,父表在前子表在后,一次跑完不中断。

5.2 触发器里的表名和别名张冠李戴

现象:执行原文的 ctrigger,报错「对象名 'SC' 无效」;执行 strigger,报错「数据库中已存在名为 'ctrig' 的对象」;执行 check_trig,报错「对象名 's' 无效」。

原因:三处低级错误——SC 不是表名、s 不是表名、strigger 的触发器名写成了 ctrig 导致与第一个触发器重名。这些错误大概率是复制粘贴时忘了改,但 SQL Server 不会惯着你,一个字对不上就执行失败。

解决:触发器名全局唯一,改成 strigger;delete 目标改成 selectcourse;校验子查询里from s改成from student。跑任何触发器之前,先select name from sys.triggers看一眼库里已有的触发器名,避免重名踩坑。

5.3 insert 触发器自我递归,插入一条卡死全库

现象:执行文档里 insert_student 触发器之后,向 student 表插入一条学生记录,查询分析器长时间无响应,甚至报「超时时间已到」。

原因:这个触发器是 after insert,而触发器体里又执行insert into student往同一张表插数据,新插入又触发自身,形成无限递归。原文里 insert_classes、insert_college、insert_course、insert_major 等九个触发器全是同一个毛病。

解决:直接删掉这些触发器:

drop trigger insert_student; drop trigger insert_classes; drop trigger insert_college; drop trigger insert_course; drop trigger insert_depart; drop trigger insert_major; drop trigger insert_selectcourse; drop trigger insert_teachercourse; drop trigger insert_teachers;

它们的本意是「新学生加入后自动同步信息」,但实现方式完全错了。正确做法是在业务层插入数据时一次性把该写的表写全,而不是用触发器再插一遍。如果一定要用触发器做同步,得保证插入目标不是触发器自身的基表,比如往 student_log 审计表里写。

5.4 视图里 group by 不带聚合函数,SQL Server 直接报错

现象:执行create view college_major_s,报错「选择列表中的列 'student.sno' 无效,因为该列没有包含在聚合函数或 GROUP BY 子句中」。

原因:视图的 select 列表里有 sno、studentname 等多个普通列,group by 却只写了 collegename、majorname、sno、studentname、tel 里的一部分,不满足 SQL 的「分组列之外的列必须聚合」规则。

解决:如果只是想去重,把 group by 换成 distinct:

create view college_major_s as select distinct sno, studentname, collegename, majorname, tel from student;

如果是想按学院专业统计人数,改成正确的聚合写法:

create view college_major_cnt as select collegename, majorname, count(*) as stu_cnt from student group by collegename, majorname;

两种意图对应的写法完全不同,跑之前先想清楚你到底要明细还是统计。

5.5 平均成绩算成天文数字:avg 取错了列

现象:执行exec avgscoreproc '数据库原理',返回的平均成绩是一个几千上万的值,明显不对。

原因:原文存储过程里写的是select @avg = avg(grade),但 selectcourse 表里根本没有 grade 字段,grade 是年级表里的概念。这个语句要么报错,要么在某个表字段恰好叫 grade 时把年级当成成绩求平均。

解决:改成avg(selectcourse.score)。另外 @avg 用 int 会截断小数,建议整体改成:

create proc avgscoreproc @cname varchar(20), @avg decimal(5,2) output, @count int output as begin select @avg = avg(selectcourse.score), @count = count(*) from course join selectcourse on course.cno = selectcourse.cno where course.coursename = @cname end

varchar 替换 char 还能避免传参时尾部空格导致匹配失败。这种「列名看着像就复制过来」的翻车在课程设计里出现频率极高,建议每次写完存储过程都用一组已知数据跑一遍,对比手工计算结果,而不是只看「能出结果」。

6. 进阶使用:把这份 SQL Server 2005 设计搬到新环境

6.1 老语法与新版本的兼容检查

SQL Server 2005 早已停止官方支持,新机器上直接装 2019/2022 跑这份 SQL,绝大多数语句能兼容,但有三个地方要处理。一是create view里如果用到select *,新版需要先保证视图列名不冲突;二是触发器里的rollback行为一致,不用担心;三是建库语句的maxsize=2日志限制建议直接去掉。如果不想留在 SQL Server 生态,迁 MySQL 也很快,对照关系如下:

SQL Server 2005MySQL 替代
smallintsmallint 可直接用
varchar(20)varchar(20) 不变
create procdelimiter 包裹的 create procedure
create triggercreate trigger,同语法
print 输出select 代替
无自增列干扰建议加 auto_increment 主键

迁移时最烦的是建库语句差异,MySQL 没有 filename 和 filegrowth 概念,直接把 create database 换成create database studentmanagesystem default charset utf8mb4;,其余建表 SQL 基本原样能用。

6.2 装完数据怎么验证这套设计是通的

我每拿到一份课程设计 SQL,第一件事不是看文档,而是按依赖顺序插入最小测试数据集,然后逐个调存储过程验证。最小数据集是:1 个学院、1 个专业、1 个年级、1 个班级、2 个学生、1 门课程、1 个老师、2 条选课记录。插入顺序严格按外键依赖来,最后验证:

-- 按依赖顺序插入 insert into college values ('计算机学院', 01); insert into major values ('软件工程', 101, '计算机学院'); insert into grades values (2024, '计算机学院', '软件工程'); insert into classes values ('软工2401', 2024, '计算机学院', '软件工程'); insert into student values ('2024001', '张三', '男', 20, '计算机学院', '软件工程', 2024, '软工2401', '13800000001'); insert into student values ('2024002', '李四', '女', 19, '计算机学院', '软件工程', 2024, '软工2401', '13800000002'); insert into course values ('C001', '数据库原理', '计算机学院', 4); insert into depart values ('数据库教研室', 01, '计算机学院'); insert into teachers values ('T001', '王老师', '男', 35, '计算机学院', '数据库教研室', '13800000003'); insert into selectcourse values ('2024001', 'C001', 'T001', 88); insert into selectcourse values ('2024002', 'C001', 'T001', 92); -- 验证存储过程 exec scoreproc '2024001'; declare @a decimal(5,2), @b int; exec avgscoreproc '数据库原理', @a output, @b output; select @a as 平均成绩, @b as 选课人次;

如果存储过程能返回正确结果,再测触发器:delete from course where cno='C001',然后查 selectcourse 应该只剩空表。这一步过完,整个库的约束、查询、级联逻辑才算真正闭环。

这份资源我前后跑了三轮,前两轮都在给原文的笔误填坑,第三轮把触发器全部重建才跑通。从那以后我每次拿到课程设计文档,第一件事不是看代码,而是先拉一张表依赖图和一张「哪些 SQL 可能执行失败」的清单,把风险排掉再动手。这套流程帮我在课程设计和答辩准备上省了不少时间,希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 5:04:35

MATLAB实现SVR回归:参数调优、代码模板与避坑指南

简介:PDF文档专门讲解Matlab实现支持向量回归(SVR)的完整思路与代码,面向需要进行回归预测、参数寻优和算法选型的机器学习开发者与科研人员,尤其适合处理小样本、非线性回归任务。文档开篇对比多元线性回归、BP神经网…

作者头像 李华
网站建设 2026/10/2 5:04:31

SAP批量导入实战:BDC与LSMW从录屏到字段映射全解析

简介:SAP两种主流批处理工具BDC与LSMW的实操讲解文档,面向SAP顾问、ABAP开发及内部IT支持人员,重点解决数据迁移、批量维护主数据、重复事务处理等高频场景。文档从SHDB录屏入手,完整演示物料账期逐月打开业务,说明录制…

作者头像 李华
网站建设 2026/10/2 5:04:05

游戏引擎架构的本质:团队分工如何决定代码分层

做引擎这些年,我反复被问到同一个问题:到底什么是游戏引擎架构。有人觉得是把渲染、物理、动画这些模块画在一张架构图上,有人觉得是选ECS还是OOP的组织方式,还有人觉得是决定用C还是Rust。这些回答都对,但都只摸到了象…

作者头像 李华
网站建设 2026/10/2 5:04:01

从RAG到开源知识库实战:本地问答系统搭建与优化全解析

先说明下这篇博文的来龙去脉。这几天技术社区里都在转“微信开源了一个神级知识库项目”这个说法,我点进去看了好几篇,发现很多人其实没讲清楚这个项目到底是什么、能用来做什么、怎么落地。作为一个常年折腾知识库工具链的人,我决定把这块拆…

作者头像 李华
网站建设 2026/10/2 5:03:49

Yule-Walker方程实战:AR参数估计与Levinson-Durbin避坑指南

简介:这是一份关于Yule-Walker方程求解与AR模型建立的实验报告PDF,面向生物医学信号处理及CS信号分析方向的学习者,适合需要掌握自回归模型参数估计、自相关函数与矩阵方程求解的读者。资源以大学生物医学信号处理实验为背景,系统…

作者头像 李华
网站建设 2026/10/2 5:03:44

大模型推理精度与硬件匹配实战指南

1. 这不是“选精度”,而是给模型配一副合脚的跑鞋你有没有遇到过这样的情况:花大价钱买了块顶配显卡,结果跑一个开源大模型时,显卡利用率卡在30%,显存只用了不到一半,推理延迟却高得离谱?或者反…

作者头像 李华