Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
优化 PHP/MySQLi 标签显示:告别 N+1 查询,实现高效批量获取_创想鸟

优化 PHP/MySQLi 标签显示:告别 N+1 查询,实现高效批量获取

优化 PHP/MySQLi 标签显示:告别 N+1 查询,实现高效批量获取

本教程探讨了在 php/mysqli 应用中显示标签时常见的 n+1 查询性能瓶颈。针对将标签id存储为逗号分隔字符串的场景,文章详细介绍了如何通过使用 `where in` 子句和动态参数绑定,将多次独立查询优化为单次批量查询。此外,还展示了 php 8.1+ 中更简洁的参数绑定方式,旨在提升标签显示效率和系统性能。

低效的标签显示方法及问题分析

网站开发中,标签系统是常见功能。然而,当标签ID以逗号分隔的字符串形式存储在主数据表中时,如果采用逐个查询的方式来获取每个标签的名称,就会导致严重的性能问题,即所谓的 N+1 查询问题。这意味着每显示一个标签,就需要执行一次独立的数据库查询。当一个项目关联了多个标签时,数据库查询次数会急剧增加,从而降低页面加载速度和服务器资源利用率。

考虑以下原始的实现方式:

prepare("SELECT id, name FROM tags WHERE id = ? AND type = 1");    $fetchTags->bind_param("i", $tag);    $fetchTags->execute();    $fetchResult = $fetchTags->get_result();    if($fetchResult->num_rows === 0) {        print('No rows');    }    while($resultrow = $fetchResult->fetch_assoc()) {      ?>close();}?>

上述代码中,如果 $row[“tags”] 包含例如 “1,2,3,4,5” 五个标签ID,foreach 循环将执行五次数据库查询。这对于少量标签尚可接受,但随着标签数量的增加,性能瓶颈会变得非常明显。

优化方案:使用 WHERE IN 进行批量查询

解决 N+1 查询问题的关键在于将多次独立的查询合并为一次批量查询。MySQL 的 WHERE IN 子句正是为此而生,它允许我们在一个查询中匹配多个值。结合 mysqli 预处理语句的动态参数绑定,我们可以高效地实现这一目标。

立即学习“PHP免费学习笔记(深入)”;

以下是优化后的实现步骤:

将标签ID字符串转换为数组: 使用 explode() 函数将逗号分隔的标签ID字符串转换为一个ID数组。生成动态占位符: 为了在 WHERE IN 子句中使用预处理语句,我们需要为数组中的每个标签ID生成一个 ? 占位符。准备 SQL 查询: 构建包含 WHERE id IN (…) 结构的 SQL 查询语句。动态绑定参数: mysqli::bind_param() 需要一个类型字符串和对应数量的参数。我们需要根据标签ID数组的长度动态生成类型字符串(例如 iiiii 代表五个整数)并使用 … 运算符(splat operator)将数组元素作为独立参数传递。执行查询并处理结果: 执行一次查询,然后遍历结果集,一次性获取所有标签的名称。

prepare('SELECT id, name FROM tags WHERE id IN ('.$placeholders.') AND type = 1 ORDER BY id');// 4. 动态绑定参数// 根据标签数量生成类型字符串,例如 'iiiii' (假设标签ID是整数类型)$types = str_repeat('i', count($tags)); // 使用 splat 运算符 (...) 将 $tags 数组的元素作为独立的参数传递给 bind_param$fetchTags->bind_param($types, ...$tags);// 5. 执行查询$fetchTags->execute();$fetchResult = $fetchTags->get_result();// 处理结果if($fetchResult->num_rows === 0) {    print('No rows'); // 或者显示“无相关标签”} else {    foreach($fetchResult as $resultRow) {        // 确保输出到HTML的内容经过转义,防止XSS攻击        ?>close();?>

通过上述优化,无论有多少个标签,都只需要执行一次数据库查询,极大地提升了效率。

PHP 8.1+ 简化参数绑定

从 PHP 8.1 版本开始,mysqli_stmt::execute() 方法得到了增强,可以直接接受一个数组作为参数。这进一步简化了动态参数绑定的过程,无需手动生成类型字符串或使用 bind_param()。

prepare('SELECT id, name FROM tags WHERE id IN ('.$placeholders.') AND type = 1 ORDER BY id');// PHP 8.1+ 的简化绑定方式:直接将标签ID数组传递给 execute()$fetchTags->execute($tags); $fetchResult = $fetchTags->get_result();if($fetchResult->num_rows === 0) {    print('No rows');} else {    foreach($fetchResult as $resultRow) {        ?>close();?>

这种简洁的语法使得代码更加清晰和易于维护。

注意事项与最佳实践

数据库设计: 尽管本教程解决了当前存储方式下的效率问题,但从长远来看,将标签ID以逗号分隔字符串的形式存储在主表中并不是最佳实践。更推荐的数据库设计是使用多对多关系,即通过一个中间关联表(如 item_tags),将主项目与标签进行关联。这样可以更灵活地管理标签,并避免字符串操作的开销。items 表: id, name, …tags 表: id, name, typeitem_tags 表: item_id, tag_id (复合主键)安全性: 始终使用预处理语句来防止 SQL 注入攻击。本教程中的所有示例都遵循了这一原则。错误处理: 在实际应用中,应该加入更完善的错误处理机制,例如检查 prepare()、execute() 和 get_result() 的返回值,并在出现错误时记录日志或向用户显示友好的错误信息。数据类型: bind_param() 的类型字符串 (str_repeat(‘i’, count($tags))) 应该与数据库中字段的实际数据类型匹配。如果标签ID可能是字符串,则应使用 ‘s’。输出转义: 在将数据库中获取的数据输出到 HTML 页面时,务必使用 htmlspecialchars() 或 htmlentities() 函数进行转义,以防止跨站脚本攻击 (XSS)。

总结

通过将低效的 N+1 查询模式转换为高效的 WHERE IN 批量查询,我们显著提升了 PHP/MySQLi 应用中标签显示的性能。无论是使用传统的 bind_param() 结合动态类型字符串和 splat 运算符,还是利用 PHP 8.1+ 提供的 execute() 数组参数简化绑定,都能有效解决性能瓶颈。同时,开发者应持续关注数据库的最佳设计实践,并确保代码的安全性、健壮性与可维护性。

以上就是优化 PHP/MySQLi 标签显示:告别 N+1 查询,实现高效批量获取的详细内容,更多请关注php中文网其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1323487.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
PHP表单邮件发送故障排查:路径配置与文件组织最佳实践
上一篇 2025年12月12日 10:12:44
PHP header() 重定向中变量传递与字符串引用深度解析
下一篇 2025年12月12日 10:12:58

相关推荐

  • mysql数据库的完整步骤有哪些

    mysql数据库的完整步骤有哪些mysql数据库的完整步骤有哪些mysql数据库的完整步骤有哪些mysql数据库的完整步骤有哪些

    创建 MySQL 数据库步骤:安装 MySQL、创建数据库、创建表、插入数据、检索数据、更新数据、删除数据,维护数据库。具体步骤:安装 MySQL使用语法 CREATE DATABASE 创建数据库使用语法 CREATE TABLE 创建表使用语法 INSERT INTO 插入数据使用语法 SELE…

    2026年9月24日 用户投稿
    200
  • sublime怎么配置React开发环境_sublime搭建React开发环境步骤

    sublime怎么配置React开发环境_sublime搭建React开发环境步骤sublime怎么配置React开发环境_sublime搭建React开发环境步骤sublime怎么配置React开发环境_sublime搭建React开发环境步骤sublime怎么配置React开发环境_sublime搭建React开发环境步骤

    首先安装Package Control,再通过它安装Babel、Emmet、SublimeLinter等插件;接着将.js/.jsx文件语法设为JavaScript (Babel)以支持JSX高亮;然后配置ESLint实现代码检查;最后可选配置构建系统运行npm start命令。 要在 Sublim…

    2026年9月24日 用户投稿
    000
  • php-gd怎么销毁图像资源_php-gd释放内存中的图像

    使用imagedestroy()函数销毁PHP-GD图像资源以避免内存泄漏。创建的资源如$image需在处理后调用imagedestroy($image)释放,尤其在循环中应每轮结束前销毁资源,推荐结合is_resource()判断有效性,遵循“谁创建,谁销毁”原则,确保内存高效管理。 在使用 PH…

    2026年9月24日
    000
  • sublime怎么配置TypeScript自动编译_sublime集成TypeScript编译环境步骤

    sublime怎么配置TypeScript自动编译_sublime集成TypeScript编译环境步骤sublime怎么配置TypeScript自动编译_sublime集成TypeScript编译环境步骤sublime怎么配置TypeScript自动编译_sublime集成TypeScript编译环境步骤sublime怎么配置TypeScript自动编译_sublime集成TypeScript编译环境步骤

    首先安装Node.js和TypeScript,再在Sublime Text中创建自定义构建系统:1. 通过npm全局安装TypeScript并验证版本;2. 在Sublime中新建Build System,配置tsc编译命令、文件匹配规则及工作目录;3. 保存为TypeScript.sublime-…

    2026年9月24日 用户投稿
    000
  • mysql储存过程中循环语句有哪些

    mysql储存过程中循环语句有哪些mysql储存过程中循环语句有哪些mysql储存过程中循环语句有哪些mysql储存过程中循环语句有哪些

    MySQL存储过程中提供WHILE和REPEAT两种循环语句:WHILE循环:根据条件重复执行代码块,条件为真时继续执行。REPEAT循环:先执行代码块,再检查条件是否为真,为假则再次执行代码块。 MySQL存储过程中的循环语句 MySQL存储过程中支持以下两种循环语句: WHILE 循环 WHIL…

    2026年9月24日 用户投稿
    000
  • sublime怎么配置js prettier自动格式化_Sublime集成Prettier实现JS代码自动格式化

    sublime怎么配置js prettier自动格式化_Sublime集成Prettier实现JS代码自动格式化sublime怎么配置js prettier自动格式化_Sublime集成Prettier实现JS代码自动格式化sublime怎么配置js prettier自动格式化_Sublime集成Prettier实现JS代码自动格式化sublime怎么配置js prettier自动格式化_Sublime集成Prettier实现JS代码自动格式化

    首先安装Node.js和Prettier,再通过Package Control安装JsPrettier插件,配置prettier_cli_path、node_path及auto_format_on_save为true,确保保存时自动格式化JS代码。 Sublime Text 虽然轻量,但通过插件可以…

    2026年9月24日 用户投稿
    700
  • mysql存储过程保存在哪

    mysql存储过程保存在哪mysql存储过程保存在哪mysql存储过程保存在哪mysql存储过程保存在哪

    MySQL 存储过程保存在 mysql.proc 表中,该表存储了存储过程的所有信息,包括名称、定义、创建者和修改时间。 MySQL 存储过程保存在哪里? MySQL 中的存储过程保存在数据库的 mysql.proc 表中。这个表存储了所有在数据库中创建的存储过程的信息。 表结构 mysql.pro…

    2026年9月24日 用户投稿
    1700
  • 如何在Debian 10(Buster)Linux上安装MySQL

    了解如何在debian 10(buster)linux上安装mysql。本指南将引导您完成在最新版本的debian系统上安装mysql 8或mysql 5.7的步骤。 第1步 – 准备工作 首先,确保您拥有Debian 10系统的shell访问权限。如果是远程系统,可以通过SSH连接。W…

    2026年9月24日
    1000
  • mysql存储过程在哪里写

    mysql存储过程在哪里写mysql存储过程在哪里写mysql存储过程在哪里写mysql存储过程在哪里写

    MySQL 存储过程存储在 MySQL 数据库中的 mysql.proc 表中。创建存储过程需要使用 CREATE PROCEDURE 语句,调用存储过程需要使用 CALL 语句。 MySQL 存储过程存储位置 存储过程在哪里写? MySQL 存储过程存储在 MySQL 数据库中。 详细说明: 存储…

    2026年9月24日 用户投稿
    500
  • 比漫熊正版官网入口_比漫熊漫画官网正版漫画在线阅读地址

    比漫熊正版官网入口_比漫熊漫画官网正版漫画在线阅读地址比漫熊正版官网入口_比漫熊漫画官网正版漫画在线阅读地址比漫熊正版官网入口_比漫熊漫画官网正版漫画在线阅读地址比漫熊正版官网入口_比漫熊漫画官网正版漫画在线阅读地址

    比漫熊漫画官网入口为https://www.bimanxiong.com,平台涵盖恋爱、悬疑等多种题材,每日更新连载,提供高清画质与简洁界面,支持分类筛选、夜间模式及书架收藏,优化阅读体验。 比漫熊漫画官网入口地址在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来比漫熊漫画官网在线阅读入口地…

    2026年9月24日 用户投稿
    700
  • 怎么在mysql中创建一个表 mysql新建数据表步骤教程

    在 mysql 中创建表的步骤和建议包括:1. 明确业务需求,设计表结构;2. 使用 create table 语句创建表,选择合适的数据类型和设置主键、索引;3. 考虑大数据量时使用分区;4. 设置正确的字符集和排序规则;5. 谨慎使用索引;6. 使用 if not exists 避免重复创建表。…

    2026年9月24日
    100
  • mysql全文索引是什么意思

    mysql全文索引是什么意思mysql全文索引是什么意思mysql全文索引是什么意思mysql全文索引是什么意思

    MySQL 全文索引是一种特殊索引,用于提高全文搜索性能,通过存储单词的前缀来工作。它提供快速全文搜索、简易查询和部分匹配。要创建全文索引,可以使用 CREATE FULLTEXT INDEX 语法,例如:CREATE FULLTEXT INDEX index_name ON table_name …

    2026年9月24日 用户投稿
    100
  • 漫客栈免费登录网页_漫客栈官方网站漫画入口

    漫客栈免费登录网页_漫客栈官方网站漫画入口漫客栈免费登录网页_漫客栈官方网站漫画入口漫客栈免费登录网页_漫客栈官方网站漫画入口漫客栈免费登录网页_漫客栈官方网站漫画入口

    漫客栈免费登录网页入口是https://www.mankezhan.com/,该平台提供海量原创漫画资源,涵盖多种题材,支持多端阅读、离线下载与互动评论,阅读体验良好。 漫客栈免费登录网页入口地址在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来漫客栈官方网站漫画入口,感兴趣的网友一起随小编…

    2026年9月24日 用户投稿
    200
  • 163邮箱官网手机免费入口 163免费邮箱移动登录

    163邮箱官网手机免费入口 163免费邮箱移动登录163邮箱官网手机免费入口 163免费邮箱移动登录163邮箱官网手机免费入口 163免费邮箱移动登录163邮箱官网手机免费入口 163免费邮箱移动登录

    163邮箱官网手机免费入口可通过访问mail.163.com自动跳转至移动版,或在应用商店下载“网易邮箱”App登录,支持多账号管理、邮件收发、附件添加、消息推送及多设备同步,并提供登录保护、主题自定义和垃圾邮件过滤等安全与个性化功能。 163邮箱官网手机免费入口在哪里?这是不少网友都关注的,接下来…

    2026年9月24日 用户投稿
    100
  • 学好mysql数据库能找到什么工作

    学好mysql数据库能找到什么工作学好mysql数据库能找到什么工作学好mysql数据库能找到什么工作学好mysql数据库能找到什么工作

    掌握 MySQL 数据库可为求职者带来众多工作机会,包括数据库管理员、数据库开发人员、数据分析师、数据科学家、商业智能分析师、软件工程师、Web 开发人员、测试工程师和数据挖掘工程师。 学好 MySQL 数据库能找到哪些工作? 精通 MySQL 数据库可为求职者创造众多职业机会,包括: 数据库管理员…

    2026年9月24日 用户投稿
    300
  • sublime的session文件是做什么用的_sublime会话文件作用与恢复机制

    sublime的session文件是做什么用的_sublime会话文件作用与恢复机制sublime的session文件是做什么用的_sublime会话文件作用与恢复机制sublime的session文件是做什么用的_sublime会话文件作用与恢复机制sublime的session文件是做什么用的_sublime会话文件作用与恢复机制

    Sublime Text的session文件记录了打开的文件、光标位置、代码折叠状态、窗口布局及未保存内容等信息,位于系统特定目录下的Local文件夹中,以JSON格式存储,通过自动保存机制在重启后恢复编辑状态。 Sublime Text 的 session 文件主要用于保存用户当前编辑环境的状态信…

    2026年9月24日 用户投稿
    000
  • mysql的全文检索是什么

    mysql的全文检索是什么mysql的全文检索是什么mysql的全文检索是什么mysql的全文检索是什么

    摘要:MySQL 全文检索是一种在文本中搜索单词或短语的技术。其工作原理是:将文本拆分为标记并存储在全文索引中。匹配文本列中标记的搜索词或短语。提供快速搜索、相关性排序、模糊搜索和部分匹配功能。 MySQL 全文检索 全文检索是一种用于在文本内容中搜索单词或短语的技术。MySQL 中的全文检索功能允…

    2026年9月24日 用户投稿
    200
  • mysql中rand的用法 mysql随机函数使用教程

    mysql 的 rand() 函数返回 0 到 1 之间的随机浮点数,用于随机选择和排序数据。1)随机排序:select from your_table order by rand()。2)随机抽取记录:select from your_table order by rand() limit 10。…

    2026年9月24日
    300
  • 高质量免费logo设计网站 国产免费logo生成工具推荐

    国产免费Logo设计网站推荐即时设计、DesignEvo、牛人设计等,这些平台提供海量模板、支持中文输入与AI智能生成,具备全中文界面、本土化元素和矢量导出功能,适合零基础用户快速制作高质量Logo。 高质量免费logo设计网站国产免费logo生成工具推荐这是不少网友都关注的接下来由PHP小编为大家…

    2026年9月24日
    300
  • 为什么GPU显存带宽比容量更重要?

    显存带宽比容量更重要,因其直接决定数据传输速度,影响GPU计算单元的利用率。在AI训练和高分辨率渲染中,高带宽可避免“数据饥饿”,确保海量数据高效流转,而HBM技术凭借3D堆叠和宽接口提供远超GDDR的带宽,成为高性能计算的关键。 GPU显存带宽比容量更重要,核心在于现代GPU的工作模式和其处理的数…

    2026年9月24日
    200

发表回复

登录后才能评论
关注微信