☰
13万条菜谱数据MySQL入库指南:表结构、导入避坑与查询优化
2026/10/13 3:27:56 网站建设 项目流程

简介:这份MySQL菜谱资源包包含十三万条菜品数据,面向餐饮应用开发者、数据分析师及菜谱分类研究者,适用于产品原型搭建、菜品标签训练、多维度分析等场景,也能满足课程设计与毕业设计的数据需求。包内共四个文件,核心为三个SQL脚本,分别建立catalog目录表、dishes菜谱表及link目录关联表,另有一个txt说明文档解释表结构与字段含义,整个压缩包大小为52.48MB。目前已有九百四十一人学习下载。数据库表结构清晰,目录与菜谱通过关联表灵活映射,支持按分类批量检索菜品,方便练习多表查询与数据迁移;同时资源附带菜谱图片下载渠道,可对照菜品外观辅助理解,进一步提升数据可用性。对开发者而言,无需爬虫清洗即可直接导入使用;对学习者而言,是理解MySQL建表逻辑、关联查询和数据库导入导出的良好素材,整体性价比高,值得收藏。

1. 13万条菜谱数据入库:这份MySQL资源能省你两周爬虫时间

做餐饮类项目或者想搭个食谱网站的人,最头疼的往往不是业务逻辑,而是没有像样的数据。自己写爬虫去抓菜谱网站,先不说反爬有多恶心,光是清洗图片、整理分类、统一字段格式就够折腾大半个月。我拆过不少数据包,这份菜谱MySQL数据算是对新手最友好的那种:13万条菜谱记录、36G菜品图片、三张表结构清清楚楚,下载下来导入MySQL就能直接查询。它适合三类人:练手SQL的初学者、做餐饮推荐系统需要大量样本的开发者、还有给毕设或Demo项目找现成数据的学生。不夸张地说,这份数据能帮你把项目启动时间从两周压缩到半天。

2. 导入前的准备工作:先把表结构和字符集摸清楚

2.1 数据包里的内容与三张表的分工

压缩包里总共五个文件:catalog.sql、dishes.sql、link.sql、说明.txt,外加一个菜谱数据13万条.rar。核心就是三个SQL文件,分别对应三张表。

catalog是目录表,存菜谱分类,比如川菜、粤菜、烘焙、主食这些大类。dishes是菜谱主表,13万条数据主要集中在这里,每条记录包含菜名、食材、步骤、图片路径等核心字段。link是关联表,负责把目录和菜谱多对多地连起来——一道菜可能同时属于“家常菜”和“快手菜”两个分类,靠link表就能优雅地表达这种关系。

一个关键设计是图片和数据库分离。数据库里只存图片路径或URL,真正36G的图片文件单独放在百度网盘,提取码l03i。这个设计很务实,否则SQL文件会膨胀到几个G,导入时长和失败率都会指数上升。

2.2 导入前的环境检查:版本、编码、内存三个参数

导入MySQL之前,我习惯先把环境确认一遍,省得导入到一半翻车。MySQL版本建议5.7以上,8.0也行,两个版本对这三个SQL文件的语法兼容性都不错。

字符集是重中之重。这类数据包用utf8mb4的概率极高,因为菜谱里有大量生僻字和特殊符号——比如“𠮷”这种扩展区汉字,utf8存不下,只有utf8mb4能搞定。导入前先在MySQL里确认默认字符集:

mysql -u root -p -e "SHOW VARIABLES LIKE 'character_set%';"

如果看到character_set_server不是utf8mb4,最好在建库的时候显式指定,别依赖全局配置:

CREATE DATABASE IF NOT EXISTS cookbook DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci;

utf8mb4_general_ci是排序规则,ci是case insensitive(不区分大小写)。对菜谱这种中文数据,用general_ci就够了,性能比unicode_ci略好,没必要上更严格的排序规则。

还有一个容易忽略的参数是max_allowed_packet。13万条数据的SQL文件,单条INSERT语句可能包着几十行记录,默认4M的包大小很容易触发Packet too large错误。建议导入前调大:

SET GLOBAL max_allowed_packet = 128M;

这个参数只对当前会话生效,重启MySQL会重置,但导入期间足够了。

3. 导入与验证:从SQL文件到可查询的完整流程

3.1 用source命令导入及三个关键参数

导入大SQL文件,我最常用的是source命令而不是mysql < file.sql重定向。原因是source是在MySQL客户端内部执行,出错时能看到具体哪一行报错,排查起来方便得多。

mysql -u root -p cookbook --default-character-set=utf8mb4

进入客户端后执行:

source /data/sql/catalog.sql; source /data/sql/dishes.sql; source /data/sql/link.sql;

执行顺序有讲究:先导入catalog和dishes,因为它们不依赖其他表;最后导入link,因为link表要引用前两张表的主键。如果link.sql里有外键约束定义,顺序反了会直接报错Cannot add foreign key constraint。

导入时sql_mode也可能捣乱。如果MySQL的sql_mode里带了ONLY_FULL_GROUP_BY或STRICT_TRANS_TABLES,某些历史数据写入时可能因为字段过长或类型不匹配被拒绝。我一般导入前先放宽约束:

SET SESSION sql_mode = '';

这个操作有风险吗?有一点。sql_mode为空意味着MySQL会更宽容地处理非法值,比如超长字符串会被截断而不是报错。但针对第三方数据包的初次导入,这是最稳妥的做法,先让数据进去,后面再慢慢清洗。

3.2 验证导入结果:表行数与抽样检查

导入完成后别急着开心,先验证数据完整性。三个最基础的检查:

SELECT COUNT(*) FROM catalog; SELECT COUNT(*) FROM dishes; SELECT COUNT(*) FROM link;

正常情况,dishes表应该接近13万条。catalog表看分类数,几百到几千都正常。link表通常比dishes多,因为多对多关系会产生更多关联记录。

然后再抽样看数据长什么样:

SELECT id, name, category FROM dishes LIMIT 5;

重点看中文字段有没有乱码。如果出现???或国这种惨不忍睹的内容,说明导入时的字符集还是没对齐,需要检查--default-character-set=utf8mb4是否真的生效了。

还可以检查图片路径字段是否完整:

SELECT img_url FROM dishes WHERE img_url IS NULL OR img_url = '' LIMIT 10;

如果返回大量空值,说明图片映射有缺失,后面对接图片时可能会踩坑。这个检查能提前暴露问题,别等到写查询接口了才发现图片全挂。

4. 关联查询与图片映射:把三张表变成一个可用数据源

4.1 核心关联SQL:catalog-dishes-link的使用方式

三张表的核心价值在于组合查询。我给你展示几种常态查询结构。

按分类查菜谱,这是最基本的联表:

SELECT c.name AS category_name, d.name AS dish_name, d.img_url FROM catalog c JOIN link l ON c.id = l.catalog_id JOIN dishes d ON l.dish_id = d.id WHERE c.name = '川菜' LIMIT 20;

这个查询把链路解释得很清楚:link表就像一座桥,左连catalog右连dishes。没有link表,分类和菜谱就得通过LIKE '%川菜%'这种模糊匹配来关联,性能和数据整洁度都会差很多。

统计每个分类下有多少道菜:

SELECT c.name, COUNT(d.id) AS dish_count FROM catalog c LEFT JOIN link l ON c.id = l.catalog_id LEFT JOIN dishes d ON l.dish_id = d.id GROUP BY c.id, c.name ORDER BY dish_count DESC LIMIT 15;

注意我用的是LEFT JOIN而不是INNER JOIN。原因很简单:有些分类可能暂时没有关联任何菜谱,如果用INNER JOIN,这些分类会直接消失;LEFT JOIN能保留分类主体,COUNT结果自然就是0。分析数据分布时,这个细节直接影响结论。

把多个表的数据组合成一个宽表视图也方便。菜谱有食材字段,分类有自己的名称,应用层面上我习惯做一张视图:

CREATE VIEW v_dish_full AS SELECT d.id AS dish_id, d.name AS dish_name, d.ingredients, d.steps, d.img_url, GROUP_CONCAT(c.name) AS categories FROM dishes d LEFT JOIN link l ON d.id = l.dish_id LEFT JOIN catalog c ON l.catalog_id = c.id GROUP BY d.id;

GROUP_CONCAT把一道菜的所有分类拼成一个逗号分隔的字符串,应用层一次查询就能拿到带全部分类标签的菜谱数据,不用再发第二轮查询。

4.2 图片文件与数据库记录的对应关系

36G图片的对接方式要理解清楚。数据库里存的img_url字段,通常是相对路径或文件名。比如/images/123.jpg这种。网盘下载的图片目录应该和这个路径结构保持一致。

我一般这么验证映射关系:先取一条记录看路径,再去本地图片目录找对应文件。

SELECT name, img_url FROM dishes LIMIT 3;

然后在本地图片目录做存在性检查。这里给一个Linux下用脚本批量验证的思路:

# 提取所有图片路径,检查文件是否存在 mysql -u root -p cookbook -N -e "SELECT img_url FROM dishes WHERE img_url IS NOT NULL" | while read path; do if [ ! -f "/data/images/$path" ]; then echo "MISSING: $path" fi done | head -50

看到MISSING输出的比例,你就能估算图片完整度。如果缺失率低于1%,算是高质量数据;超过5%,就得考虑是否值得花时间补图了。

图片存储上有个实操建议:不要直接读网盘里的原目录做线上服务。36G图片放机械盘或NAS上,随机读取的性能很拉胯。我一般会把图片转存到本地SSD或对象存储,并开启CDN加速。对菜谱这种图片尺寸不一的场景,还可以用npx sharp-cli批量压缩成WebP格式,能在保持观感的前提下缩小70%体积。

5. 避坑清单:乱码、导入失败和字段逻辑错位

5.1 导入报错Unknown collation: utf8mb4_0900_ai_ci

这是MySQL 5.7和8.0之间最常见的兼容性问题。如果SQL文件是用MySQL 8.0导出的,表定义里可能带着utf8mb4_0900_ai_ci这个排序规则,而5.7版本根本不认识它。

原因:utf8mb4_0900_ai_ci是8.0专属,5.7的字符集列表里没有这个字段。解决方式是导入前先批量替换SQL文件里的排序规则名称:

sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_general_ci/g' dishes.sql

替换完再导入,大概率能过。注意sed -i会直接改原文件,建议先备份一份再操作。

5.2 导入进行到一半,终端卡住不动

13万条数据的SQL文件即便拆过表,也有几十MB甚至上百MB。用source导入时,如果终端光标一直跳但进度不显示,很多人会以为卡死了。

原因:MySQL客户端在慢慢执行大批量INSERT,磁盘IO成了瓶颈,尤其是机械硬盘,写入速度可能只有50MB/s。解决方式是先看MySQL进程是否还在跑:

SHOW PROCESSLIST;

如果能看到Query状态且时间在持续变化,就是在正常干活,等就行。想加速的话,导入前关掉自动提交和唯一性检查:

SET SESSION autocommit = 0; SET SESSION unique_checks = 0; SET SESSION foreign_key_checks = 0;

这组参数能让导入速度翻倍,因为MySQL不用每条INSERT都刷盘、不用每行都查外键约束。导入完记得手动提交一次:

COMMIT;

5.3 菜谱表和关联表对不上号

导入一切正常,但联表查询时发现大量菜谱没有分类,或者分类下没几道菜。

原因:多半是link表数据不完整,或者导入顺序错误导致外键关系错位。检查一下关联记录数是否合理:

SELECT COUNT(*) FROM link; SELECT COUNT(DISTINCT dish_id) FROM link; SELECT COUNT(DISTINCT catalog_id) FROM link;

COUNT(DISTINCT dish_id)如果远小于dishes表的行数,说明一部分菜谱确实没有关联任何分类。这时候不用慌,写查询时用LEFT JOIN兜底就行,别让分类缺失影响主数据展示。

5.4 图片路径带了特殊前缀,实际文件不存在

有时候img_url存的是完整URL(比如https://example.com/images/123.jpg),而本地图片目录用的是纯文件名。直接拿URL去匹配文件系统,肯定全是MISSING。

解决方式是清洗字段,把URL转成本地路径:

UPDATE dishes SET img_url = REPLACE(img_url, 'https://example.com', '') WHERE img_url LIKE 'https://example.com%';

REPLACE函数把域名前缀剥掉,只留/images/123.jpg这种相对路径,再拿去和本地文件比对就顺了。注意执行前先SELECT确认替换范围正确,别误伤正常数据。

6. 进阶技巧:用MySQL生成的二级缓存表做热数据加速

数据能查了,图片能看了,下一步就是优化读取性能。菜谱类应用的高频查询往往是“按分类浏览”“查看详情”,这些查询每次都要联三张表,并发一高MySQL就吃力。

我的做法是生成一张二级缓存表,把高频查询结果提前物化:

CREATE TABLE dishes_cache AS SELECT d.id AS dish_id, d.name AS dish_name, d.ingredients, d.steps, d.img_url, GROUP_CONCAT(c.name) AS categories FROM dishes d LEFT JOIN link l ON d.id = l.dish_id LEFT JOIN catalog c ON l.catalog_id = c.id GROUP BY d.id;

然后给常用查询字段建索引:

ALTER TABLE dishes_cache ADD PRIMARY KEY (dish_id), ADD FULLTEXT INDEX idx_name (dish_name);

FULLTEXT索引是MySQL里做中文全文搜索的合法方案,比LIKE '%菜名%'快一两个数量级。用MATCH...AGAINST查询:

SELECT * FROM dishes_cache WHERE MATCH(dish_name) AGAINST('红烧肉' IN NATURAL LANGUAGE MODE) LIMIT 10;

IN NATURAL LANGUAGE MODE适合人话输入,MySQL会分词后按相关性排序。注意中文分词质量一般,搜长尾词可能不准,但作为Demo或内部工具完全够用。

从那以后我每次拿外部数据包建应用,都强制走一遍“先建缓存表、再建全文索引、最后接接口”的流程,再也不怕并发查询打崩数据库了。这份菜谱数据做练习也好、做项目基底也罢,都算得上是一份靠谱的素材,希望帮到你。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询