介绍MySQL数据库的预处理(prepared statement)性能测试
免费学习推荐:mysql视频教程
1、预处理干了什么
当我们提交一条数据库语句时,语句到达数据库服务那边,数据库服务需要解析这条sql语句,比如说语法检查,查询条件先后优化,然后才执行。对于预处理,简单来说就是把客户端与数据库服务原本一次交互的分成两次。首先,提交数据库语句,让数据库服务先解析这条语句。其次,提交参数,调用语句并执行。这样对于多次重复执行的语句来说,可以提交并解析一次数据库语句就可以了,然后不断的调用刚刚解析过得语句并执行。这样就省去了多次解析同一条语句的时间。从而达到提高效率的目的。
预处理语句支持占位符(place holder),通过绑定占位符的方式提交参数。一个非常重要的一点是,能与占位符绑定的只能是值,而不能是sql语句的一些关键词。例如语句:“select * from student where student.id = ?”。如果放入占位符(?)中的是“1 or 1=1”,那么“1 or 1=1”就会被当成一个值,即用``符号包括起来,最终这条非法的语句就出错了。从而达到放sql注入的漏洞(sql injestion)。
预处理机制主要的三步骤:
1、将语句进行预处理
2、执行语句
3、析构掉预处理语句。
2、关于`performance_schema`.`prepared_statements_instances` 表的介绍
运行sql脚本:show global variable like ‘%prepare%’。 可以看到一个叫‘performance_schema_max_prepared_statement_instances
’的系统变量。其值为0表示不启用预处理语句性能数据记录表
`performance_schema`.`prepared_statements_instances`;-1表示记录的数量动态处理;其他正整数值则表示performance_schema_max_prepared_statement_instances
记录的最大条数。
表`performance_schema`.`prepared_statements_instances`又是什么呢?它是用来记录预处理语句的一些基本信息和性能数据。比如预处理语句的ID,预处理语句的名字,预处理语句的具体语句内容,预处理语句被执行的次数,每次执行耗时,每条预处理语句所属的线程id等。当我们创建一条预处理语句时,就会插入一条数据到这张表里。预处理语句是基于连接的,连接断开,则预处理语句自动删除。但`performance_schema`.`prepared_statements_instances`表是全局的,它与数据库连接没关系。有了这些数据,我们就可以知道,1、代码中执行的语句是否真的做了预处理,2、通过了解预处理语句的执行情况来决定业务中是否需要把一个语句进行预处理。
3、qt prepare函数说明
根据我自己本身的项目需求,这次测试的客户端代码使用的是Qt。这里记录一个关键的函数:QSqlQuery类的prepare函数。调用prepare函数即是向数据库提交一个创建预处理语句的命令。意味着调用期间,是会与数据库服务进行一次交互的。需要注意的是,当同一个QSqlQuery类对象调用第二次prepare时,会将第一次调用prepare创建的预处理语句删除掉,然后再创建一条预处理语句,即便是这两条预处理语句是一模一样的。在调用QSqlQuery的exec函数时,也会将QSqlQuery先前创建的预处理语句删除掉。所以在查询结束,关闭掉连接,或者查询又执行了其他语句,从而导致`performance_schema`.`prepared_statements_instances`表没有相关预处理语句的记录,就会误认为预处理语句创建失败。其实Qt的这种做法,也省去了要我们人为的删除预处理语句。
4、实验猜想
常规执行的语句和预处理后执行的语句不同点在于,在多次执行的情况下,预处理语句只需解析一次sql语句,而之后多花时间在传输参数和绑定参数上。预处理语句在返回结果时,使用的是二进制传输协议,而普通语句使用的是文本格式的传输协议。因此我们做出以下猜想并验证。
1、如果执行的是简单语句,那么普通执行和预处理执行性能上差别不大。预处理语句在重复执行复杂的语句情况下才展现出优势。
2、在查询结果集是大数据量的情况下,预处理语句会展现出性能优势。
5、实验数据记录
序号 | 是否预处理 | 语句 | 是否远程数据库 | 返回数据量 | 每次实验语句执行总次数 | 三次实验平均总耗时/单位毫秒 |
1 | 是 | select * from task where task.taskId in (?) | 是 | 1000 | 1000 | 69822 |
2 | 否 | select * from task where task.taskId in (arr) | 是 | 1000 | 1000 | 66778 |
3 | 是 | select * from task where task.taskId = ? | 是 | 1 | 1000 | 1260 |
4 | 否 | select * from task where task.taskId = id | 是 | 1 | 1000 | 951 |
5 | 是 | select * from task a LEFT JOIN task_file b ON a.taskId = b.task_id where a.taskName like '%s%' and b.file_id > 100000 and b.file_id < 200000 and a.taskId = ?"; | 是 | 2 | 1000 | 2130 |
6 | 否 | select * from task a LEFT JOIN task_file b ON a.taskId = b.task_id where a.taskName like '%s%' and b.file_id > 100000 and b.file_id < 200000 and a.taskId = 32327"; | 是 | 2 | 1000 | 1480 |
7 | 是 | select * from task where task.taskId in (?) | 否 | 1000 | 1000 | 57051 |
8 | 否 | select * from task where task.taskId in (arr) | 否 | 1000 | 1000 | 56235 |
9 | 是 | select * from task where task.taskId = ? | 否 | 1 | 1000 | 217 |
10 | 否 | select * from task where task.taskId = id | 否 | 1 | 1000 | 204 |
11 | 是 | select * from task a LEFT JOIN task_file b ON a.taskId = b.task_id where a.taskName like '%s%' and b.file_id > 100000 and b.file_id < 200000 and a.taskId = ?"; | 否 | 2 | 1000 | 366 |
12 | 否 | select * from task a LEFT JOIN task_file b ON a.taskId = b.task_id where a.taskName like '%s%' and b.file_id > 100000 and b.file_id < 200000 and a.taskId = 32327"; | 否 | 2 | 1000 | 380 |
6、结论
实验的数据结果和我预期的相差有点儿大,但经过反复检查测试代码和测试过程,确认测试本身应该没有问题。尊重实验数据,我们得出以下结论:
1、通过实验5和实验6对比,实验11和实验12对比,可得猜想1是错误的。结论应该是:MySQL预处理和常规查询在简单语句和复杂语句下,都没有显著性的性能差别。
2、通过实验1和实验2对比,实验7和实验8对比,可得猜想2是错误的。结论应该是:MySQL预处理和常规查询的结果在数据传输上没有显著性的性能差距。
3、此外,对比远程数据库和本地数据库实验数据。可得结论:MySQL数据库在本地会给数据操作带来显著性的性能提高。
相关免费学习推荐:mysql数据库(视频)
以上是介绍MySQL数据库的预处理(prepared statement)性能测试的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

MySQL适合初学者使用,因为它安装简单、功能强大且易于管理数据。1.安装和配置简单,适用于多种操作系统。2.支持基本操作如创建数据库和表、插入、查询、更新和删除数据。3.提供高级功能如JOIN操作和子查询。4.可以通过索引、查询优化和分表分区来提升性能。5.支持备份、恢复和安全措施,确保数据的安全和一致性。

Navicat本身不存储数据库密码,只能找回加密后的密码。解决办法:1. 检查密码管理器;2. 检查Navicat的“记住密码”功能;3. 重置数据库密码;4. 联系数据库管理员。

使用 Navicat Premium 创建数据库:连接到数据库服务器并输入连接参数。右键单击服务器并选择“创建数据库”。输入新数据库的名称和指定字符集和排序规则。连接到新数据库并在“对象浏览器”中创建表。右键单击表并选择“插入数据”来插入数据。

MySQL是一个开源的关系型数据库管理系统。1)创建数据库和表:使用CREATEDATABASE和CREATETABLE命令。2)基本操作:INSERT、UPDATE、DELETE和SELECT。3)高级操作:JOIN、子查询和事务处理。4)调试技巧:检查语法、数据类型和权限。5)优化建议:使用索引、避免SELECT*和使用事务。

Navicat for MariaDB 无法直接查看数据库密码,因为密码以加密形式存储。为确保数据库安全,有三个方法可重置密码:通过 Navicat 重置密码,设置复杂密码。查看配置文件(不推荐,风险高)。使用系统命令行工具(不推荐,需要对命令行工具精通)。

在 Navicat 中执行 SQL 的步骤:连接到数据库。创建 SQL 编辑器窗口。编写 SQL 查询或脚本。单击“运行”按钮执行查询或脚本。查看结果(如果执行查询的话)。

可在 Navicat 中通过以下步骤新建 MySQL 连接:打开应用程序并选择“新建连接”(Ctrl N)。选择“MySQL”作为连接类型。输入主机名/IP 地址、端口、用户名和密码。(可选)配置高级选项。保存连接并输入连接名称。

MySQL和SQL是开发者必备技能。1.MySQL是开源的关系型数据库管理系统,SQL是用于管理和操作数据库的标准语言。2.MySQL通过高效的数据存储和检索功能支持多种存储引擎,SQL通过简单语句完成复杂数据操作。3.使用示例包括基本查询和高级查询,如按条件过滤和排序。4.常见错误包括语法错误和性能问题,可通过检查SQL语句和使用EXPLAIN命令优化。5.性能优化技巧包括使用索引、避免全表扫描、优化JOIN操作和提升代码可读性。
