应选mediumtext或longtext字段并垂直分表,因text仅64kb易截断;需显式声明类型、禁用自动过滤、避免like查询、列表页field指定字段、大字段拆至扩展表且外键加索引。

ThinkPHP 5.1 处理 MySQL 的 TEXT 或 LONGTEXT 字段,性能瓶颈往往不在 PHP 层,而在数据组织方式和查询习惯上。只要字段内容可能超几 KB(比如富文本、日志、JSON、base64 图片),就别把它和用户 ID、状态、时间戳这些轻量字段挤在一张表里查。
建表阶段就该选对类型并拆分
别依赖 Migration 自动生成的 $table->text()——它对应 MySQL 的 TEXT(64KB 上限),实际很容易超限。按预估长度手动指定:
- 普通长文、评论、带样式的 HTML:用
$table->mediumText('content')(最大 16MB) - 含附件列表、完整请求/响应日志、大配置块:直接用
$table->longText('raw_data')(4GB) - 多个大字段(如 content、log、extra)必须垂直拆分到独立扩展表,主表只留结构化字段,外键加索引
查询时永远显式指定字段
哪怕只是列表页展示标题和作者,也绝不能写 select() 或 find() 不带 field()。TEXT 字段一参与 SELECT,MySQL 就可能放弃内存临时表、触发磁盘 IO、拖慢整条 SQL:
- 列表页:只查
field('id,title,status,created_at') - 详情页再单独查扩展表:
Db::name('article_content')->where('article_id', $id)->find() - 关联查询中,
with()闭包里也要加field(),避免把大字段一起捞出来
模型层关掉自动过滤和转义
ThinkPHP 5.1 默认对字符串字段做 htmlspecialchars 和 trim,这对富文本是灾难性的——<script></script> 被干掉、Markdown 缩进被抹平、JSON 格式错乱:
- 在模型中声明:
protected $filter = ['content' => ''];(仅禁用该字段) - 或全局关闭:
protected $filter = []; - 避免使用
$model->data($data, true)严格模式处理含 HTML 的数据;改用手动赋值:$model->content = $raw_html;
别在 WHERE 里对 TEXT 字段做模糊搜索
where('content', 'like', '%关键词%') 必然全表扫描,十万行数据下查询秒变数秒。这不是加索引能解决的:
- 真正需要检索时,弃用 MySQL 原生 LIKE,接入 Elasticsearch 或 Xunsearch
- 若只是偶尔查最大长度记录,可用
field('*, LENGTH(content) as len')->order('len', 'desc')->limit(1),但注意大数据量时仍会遍历计算 - 高频按长度筛选场景,建议冗余一个
content_length字段并建索引,插入/更新时同步维护
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











