- 单行注释
- 多行注释
- 可执行注释
- 为什么要把可执行的 SQL 语句写在注释里面呢?
- 注释示例
- 导入数据时禁止/激活索引
- 测试禁止索引再导入数据的效率
SELECT * from tf_user; # 单行注释,从这个注释符号起直到该行结束
SELECT * from tf_user; -- 单行注释,从这个注释符号起直到该行结束
多行注释
/*
this is multiline comment
*/
SELECT * from tf_user;
可执行注释
使用 MySQL 的命令 mysqldump 导出的备份脚本文件中,你会看到大量如下所示的特殊注释语句:
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!...*/
这叫可执行的注释(Executable Comments),注释当中的语句会被 MySQL 正常解析和执行,但在其他数据库管理系统将被作为注释忽略,这可以提高数据库脚本的可移植性。
MySQL 包含一些其它 DBMS 中不具备的功能扩展,如果使用了它们,将无法把代码移植到其它 DBMS 中。在某些情况下,你可以编写包含 MySQL 特殊扩展功能的代码,但仍保持其可移植性,方法是用 /*!... */
注释掉这些扩展。MySQL DBMS 能够解析并执行注释中的代码,就像对待其它 MySQL 语句一样,但其它 DBMS 则将其当成注释,从而忽略这些扩展功能。
也就是说,把 SQL 语句放在 /*! ... */
中,这些语句在其它数据库中是不会被执行,但在 MySQL 中它会被执行,在其它数据库中 /*! ... */
就仅是注释。
以下是在备份文件开头会出现的注释语句:
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
说明:
-
40101,这是 MySQL 版本号,该数字告诉我们这些语句只有在大于等于该版本的 MySQL 中才能执行,即在 MySQL 4.1.1(4.01.01)及以上版本的 MySQL 中执行
-
上述注释语句中的第一条 SET 语句,是将当前系统变量 CHARACTER_SET_CLIENT 的值赋值给用户变量 @OLD_CHARACTER_SET_CLIENT
以下是在备份文件末尾会出现的注释语句,使用 SET 语句恢复服务器系统变量原来的值:
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
导入数据时禁止/激活索引
LOCK TABLES `td_appraise_dimension` WRITE;
/*!40000 ALTER TABLE `td_appraise_dimension` DISABLE KEYS */;
INSERT INTO `td_appraise_dimension` VALUES (1,'管理氛围',20,1),(2,'福利待遇',25,2),(3,'面试经历',15,3),(4,'实力前景',15,4),(5,'CEO能力',25,5);
/*!40000 ALTER TABLE `td_appraise_dimension` ENABLE KEYS */;
UNLOCK TABLES;
说明:
- DISABLE KEYS 是禁止索引
- ENABLE KEYS 是激活索引
- 在插入数据时,都会先禁止索引,再激活索引,这样可以节省导入数据的时间
有一个表 tbl1 的结构如下:
CREATE TABLE `tbl1` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` char(20) NOT NULL default '',
PRIMARY KEY (`id`),
KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
该表里已经存在了 200 万条记录. 现在, 需要把 tbl1 中的所有记录全部导到另一个完全相同的表 tbl2 中去:
- 如果采用以下传统的方式, 则执行时间为: 98.01s
mysql>INSERT INTO tbl2 SELECT * FROM tbl1;
Query OK, 2000000 row affected (1 min 38.01 sec) Records: 2000000 Duplicates: 0 Warnings: 0
- 如果是用以下SQL语句, 则执行时间为: 80.85s (36.30 + 44.55)
mysql>ALTER TABLE tbl2 DISABLE KEYS;
Query OK, 0 rows affected (0.00 sec)
mysql>INSERT INTO tbl2 SELECT * FROM tbl1;
Query OK, 2000000 row affected (36.30 sec) Records: 2000000 Duplicates: 0 Warnings: 0
mysql>ALTER TABLE tbl2 ENABLE KEYS;
Query OK, 0 rows affected (44.55 sec)
从上面的测试结果来看,在大批量导入时先禁用索引,在完全导入后, 再开启索引,一次性完成重建索引的效率会相对高很多,经过反复几次测试,感觉后者基本能比前者快 1.2 倍左右。这也就是 LOAD DATAL INFILE 相对较快的原因之一。