一、MySQL游标简介
MySQL在服务器端提供只读的、单向的游标,而且只能在存储过程或者更底层的客户端API中使用。
MySQL游标是只读的,因为它指向的对象存储在临时表中而非实际查询到的数据。它可以逐行指向查询结果,然后让程序做进一步的处理。在一个存储过程中,游标可以被多次使用并且可以被“嵌套”在循环结构中。
MySQL的游标设计也为粗心的人“准备”了陷阱。因为是使用临时表实现的,所以它在效率上给开发人员一个错觉。打开游标时需要执行整个查询是最重要的要注意的事项。
考虑下面的存储过程:
CREATE PROCEDURE bad_cursor() BEGIN DECLARE film_id INT; DECLARE f CURSOR FOR SELECT film_id FROM sakila.film; OPEN f; FETCH f INTO film_id; CLOSE f; END
这个例子表明,游标在处理未完成的数据时可以立即关闭。使用Oracle或者SQL Server的用户不会认为这个存储过程有什么问题,但是在MySQL中,这会带来很多的不必要的额外操作。使用SHOW STATUS来诊断这个存储过程,可以看到它需要做1000个索引页的读取,做1000个写入。在打开游标动作的第五行发生了1000次读写操作,原因在于表sakila.film中有1000条记录。
这个案例告诉我们,如果在关闭游标的时候你只是扫描一个大结果集的一小部分,那么存储过程可能不仅没有减少开销,相反带来了大量的额外开销。这时,你需要考虑使用LIMIT来限制返回的结果集。
使用游标可能导致MySQL执行一些额外的低效I/O操作。因为临时内存表不支持BLOB和TEXT类型,如果游标返回的结果包含这样的列的话,MySQL就必须创建临时磁盘表来存放,这样性能可能会很糟。即便没有该列,当临时表超过tmp_table_size大小时,MySQL仍会在磁盘上创建临时表。
虽然MySQL不支持客户端游标,但可以通过客户端API缓存所有查询结果来模拟游标。这和直接将结果放在一个内存数组中来维护并没有什么不同。
二、绑定变量
从MySQL 4.1版本开始,就支持服务器端的绑定变量(prepared statement),这大大提高了客户端和服务器端数据传输的效率。如果你使用支持新协议的客户端,例如MySQL CAPI,就可以使用绑定变量功能。另外,Java和.NET的也都可以使用各自的客户端Connector/J和Connector/NET来使用绑定变量。
最后,还有一个SQL接口用于支持绑定变量,后面我们将讨论这个(这里容易引起困扰)。
客户端向服务器发送一份 SQL 语句的模板,以创建一个绑定变量的 SQL。服务器端收到这个SQL语句框架后,解析并存储这个SQL语句的部分执行计划,返回给客户端一个SQL语句处理句柄。以后每次执行这类查询,客户端都指定使用这个句柄。
绑定变量的SQL,使用问号标记可以接收参数的位置,当真正需要执行具体查询的时候,则使用具体值代替这些问号。例如,下面是一个绑定变量的SQL语句:
INSERT INTO tbl(col1, col2, col3) VALUES (?, ?, ?);
发送该SQL句柄和各个问号参数取值到服务器端,就能执行具体的查询。反复使用这样的方式执行具体的查询,这正是绑定变量的优势所在。具体如何发送取值参数和SQL句柄,则和各个客户端的编程语言有关。使用Java和.NET的MySQL连接器就是一种办法。很多使用MySQL C语言链接库的客户端可以提供类似的接口,需要根据使用的编程语言的文档来了解如何使用绑定变量。
因为如下的原因,MySQL在使用绑定变量的时候可以更高效地执行大量的重复语句:
1.在服务器端只需要解析一次SQL语句。
2.在服务器端某些优化器的工作只需要执行一次,因为它会缓存一部分的执行计划。
以二进制的方式只发送参数和句柄,比起每次都发送ASCII码文本效率更高,一个二进制的日期字段只需要三个字节,但如果是ASCII码则需要十个字节。通过使用绑定变量的形式,BLOB和TEXT字段可以分块传输,从而达到最大的节省。这样就不需要一次性传输了。二进制协议在客户端也可能节省很多内存,减少了网络开销,另外,还节省了将数据从存储原始格式转换成文本格式的开销。
4.仅仅是参数——而不是整个查询语句——需要发送到服务器端,所以网络开销会更小。
5.MySQL在存储参数的时候,直接将其存放到缓存中,不再需要在内存中多次复制。
绑定变量相对也更安全。不需要在应用程序中处理转义,这样可以变得更加简单,同时也能大幅降低SQL注入和攻击的风险。(任何时候都不要信任用户输入,即使是使用绑定变量的时候。)
可以只在使用绑定变量的时候才使用二进制传输协议。如果使用常规的mysql_query()接口,则无法使用二进制传输协议。还有一些客户端让你使用绑定变量,先发送带参数的绑定SQL,然后发送变量值,但是实际上,这些客户端只是模拟了绑定变量的接口,最后还是会直接用具体值代替参数后,再使用mysql_query()发送整个查询语句。
2.1 绑定变量的优化
对使用绑定变量的SQL,MySQL能够缓存其部分执行计划,如果某些执行计划需要根据传入的参数来计算时,MySQL就无法缓存这部分的执行计划。根据优化器什么时候工作,可以将优化分为三类。
在本书编写的时候,下面的三点是适用的。
1.在准备阶段
服务器解析SQL语句,移除不可能的条件,并且重写子查询。
2.在第一次执行的时候
如果可能的话,服务器先简化嵌套循环的关联,并将外关联转化成内关联。
3.在每次SQL语句执行时
服务器做如下事情:
1)过滤分区。
2)如果可能的话,尽量移除COUNT()、MIN()和MAX()。
3)移除常数表达式。
4)检测常量表。
5)做必要的等值传播。
6)分析和优化ref、range和索引优化等访问数据的方法。
7)优化关联顺序。
2.2 SQL接口的绑定变量
MySQL支持了SQL接口的绑定变量。不使用二进制传输协议也可以直接以SQL的方式使用绑定变量。下面案例展示了如何使用SQL接口的绑定变量:
当服务器收到这些SQL语句后,先会像一般客户端的链接库一样将其翻译成对应的操作。
这意味着你无须使用二进制协议也可以使用绑定变量。
正如你看到的,比起直接编写的SQL语句,这里的语法看起来有一些怪怪的。
那么,这种写法实现的绑定变量到底有什么优势呢?
最主要的用途就是在存储过程中使用。在MySQL 5.0版本中,就可以在存储过程中使用绑定变量,其语法和前面介绍的SQL接口的绑定变量类似。意思是在存储过程中可以创建和运行基于动态SQL语句的代码
“动态”是指可以通过灵活地拼接字符串等参数构建SQL语句。举个例子,下面这个存储过程可以在特定的数据库中执行OPTIMIZE TABLE操作:
DROP PROCEDURE IF EXISTS optimize_tables; DELIMITER // CREATE PROCEDURE optimize_tables(db_name VARCHAR(64)) BEGIN DECLARE t VARCHAR(64); DECLARE done INT DEFAULT 0; DECLARE c CURSOR FOR SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = db_name AND TABLE_TYPE = 'BASE TABLE'; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; OPEN c; tables_loop: LOOP FETCH c INTO t; IF done THEN LEAVE tables_loop; END IF; SET @stmt_text := CONCAT("OPTIMIZE TABLE ", db_name, ".", t); PREPARE stmt FROM @stmt_text; EXECUTE stmt; DEALLOCATE PREPARE stmt; END LOOP; CLOSE c; END// DELIMITER ;
可以这样调用这个存储过程:
mysql> CALL optimize_tables('sakila')
另一种实现存储过程中循环的办法是:
REPEAT FETCH c INTO t; IF NOT done THEN SET @stmt_text := CONCAT("OPTIMIZE TABLE ", db_name, ".", t); PREPARE stmt FROM @stmt_text; EXECUTE stmt; DEALLOCATE PREPARE stmt; END IF; UNTIL done END REPEAT;
REPEAT和其他循环结构最大的不同是,它在每次循环中都会检查两次循环条件。在这个例子中,因为循环条件检查的是一个整数判断,并不会有什么性能问题,如果循环的判断条件非常复杂的话,则需要注意这两者的区别。
像这样使用SQL接口的绑定变量拼接表名和库名是很常见的,这样的好处是无须使用任何参数就能完成SQL语句。由于库名和表名都是关键字,因此在绑定变量的二进制协议中无法将这两个参数化。LIMIT子句是另一个经常需要动态设置的,因为在二进制协议中无法将其参数化。
另外,编写存储过程时,SQL接口的绑定变量通常可以很大程度地帮助我们调试绑定变量,如果不是在存储过程中,SQL接口的绑定变量就不是那么有用了。因为SQL接口的绑定变量,它既没有使用二进制传输协议,也没有能够节省带宽,相反还总是需要增加至少一次额外网络传输才能完成一次查询。所有只有在某些特殊的场景下SQL接口的绑定变量才有用,比如当SQL语句非常非常长,并且需要多次执行的时候。
2.3 绑定变量的限制
关于绑定变量的一些限制和注意事项如下:
1.绑定变量是会话级别的,所以连接之间不能共用绑定变量句柄。同样地,一旦连接断开,则原来的句柄也不能再使用了。(连接池和持久化连接可以在一定程度上缓解这个问题。)
2.在MySQL 5.1版本之前,绑定变量的SQL是不能使用查询缓存的。
3.并不是所有的时候使用绑定变量都能获得更好的性能。如果只是执行一次SQL,那么使用绑定变量方式无疑比直接执行多了一次额外的准备阶段消耗,而且还需要一次额外的网络开销。(要正确地使用绑定变量,还需要在使用完成后,释放相关的资源。)
4.当前版本下,还不能在存储函数中使用绑定变量(但是存储过程中可以使用)。
如果没有释放绑定变量的资源,服务器端很容易出现资源泄漏的情况。由于绑定变量 SQL 总数的限制是全局限制,因此在一个地方出现的错误可能会影响到所有其他线程。
6.有些操作,如BEGIN,无法在绑定变量中完成。
不过使用绑定变量最大的障碍可能是:
它是如何实现以及原理是怎样的,这两点很容易让人困惑。有时,很难解释如下三种绑定变量类型之间的区别是什么:
1.客户端模拟的绑定变量
客户端的驱动程序接收一个带参数的SQL,再将指定的值带入其中,最后将完整的查询发送到服务器端。
2.服务器端的绑定变量
客户端使用特殊的二进制协议将带参数的字符串发送到服务器端,然后使用二进制协议将具体的参数值发送给服务器端并执行。
3.SQL接口的绑定变量
客户端先发送一个带参数的字符串到服务器端,这类似于使用PREPARE的SQL语句,然后发送设置参数的SQL,最后使用EXECUTE来执行SQL。所有这些都使用普通的文本传输协议。
以上是MySQL中的游标和绑定变量是什么的详细内容。更多信息请关注PHP中文网其他相关文章!

MySQL和SQLite的主要区别在于设计理念和使用场景:1.MySQL适用于大型应用和企业级解决方案,支持高性能和高并发;2.SQLite适合移动应用和桌面软件,轻量级且易于嵌入。

MySQL中的索引是数据库表中一列或多列的有序结构,用于加速数据检索。1)索引通过减少扫描数据量提升查询速度。2)B-Tree索引利用平衡树结构,适合范围查询和排序。3)创建索引使用CREATEINDEX语句,如CREATEINDEXidx_customer_idONorders(customer_id)。4)复合索引可优化多列查询,如CREATEINDEXidx_customer_orderONorders(customer_id,order_date)。5)使用EXPLAIN分析查询计划,避

在MySQL中使用事务可以确保数据一致性。1)通过STARTTRANSACTION开始事务,执行SQL操作后用COMMIT提交或ROLLBACK回滚。2)使用SAVEPOINT可以设置保存点,允许部分回滚。3)性能优化建议包括缩短事务时间、避免大规模查询和合理使用隔离级别。

选择PostgreSQL而非MySQL的场景包括:1)需要复杂查询和高级SQL功能,2)要求严格的数据完整性和ACID遵从性,3)需要高级空间功能,4)处理大数据集时需要高性能。PostgreSQL在这些方面表现出色,适合需要复杂数据处理和高数据完整性的项目。

MySQL数据库的安全可以通过以下措施实现:1.用户权限管理:通过CREATEUSER和GRANT命令严格控制访问权限。2.加密传输:配置SSL/TLS确保数据传输安全。3.数据库备份和恢复:使用mysqldump或mysqlpump定期备份数据。4.高级安全策略:使用防火墙限制访问,并启用审计日志记录操作。5.性能优化与最佳实践:通过索引和查询优化以及定期维护兼顾安全和性能。

如何有效监控MySQL性能?使用mysqladmin、SHOWGLOBALSTATUS、PerconaMonitoringandManagement(PMM)和MySQLEnterpriseMonitor等工具。1.使用mysqladmin查看连接数。2.用SHOWGLOBALSTATUS查看查询数。3.PMM提供详细性能数据和图形化界面。4.MySQLEnterpriseMonitor提供丰富的监控功能和报警机制。

MySQL和SQLServer的区别在于:1)MySQL是开源的,适用于Web和嵌入式系统,2)SQLServer是微软的商业产品,适用于企业级应用。两者在存储引擎、性能优化和应用场景上有显着差异,选择时需考虑项目规模和未来扩展性。

在需要高可用性、高级安全性和良好集成性的企业级应用场景下,应选择SQLServer而不是MySQL。1)SQLServer提供企业级功能,如高可用性和高级安全性。2)它与微软生态系统如VisualStudio和PowerBI紧密集成。3)SQLServer在性能优化方面表现出色,支持内存优化表和列存储索引。


热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

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

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),