基于mysql时间处理函数的应用详解

DAYOFWEEK(date)

返回日期date的星期索引(1=星期天,2=星期一, ……7=星期六)。这些索引值对应于ODBC标准。

mysql> select DAYOFWEEK('1998-02-03');  

-> 3  

WEEKDAY(date)

返回date的星期索引(0=星期一,1=星期二, ……6= 星期天)。

mysql> select WEEKDAY('1997-10-04 22:23:00');  

-> 5  

mysql> select WEEKDAY('1997-11-05');  

-> 2  

DAYOFMONTH(date)

返回date的月份中日期,在1到31范围内。

mysql> select DAYOFMONTH('1998-02-03');  

-> 3  

DAYOFYEAR(date)

返回date在一年中的日数, 在1到366范围内。

mysql> select DAYOFYEAR('1998-02-03');  

-> 34  

MONTH(date)

返回date的月份,范围1到12。

mysql> select MONTH('1998-02-03');  

-> 2  

DAYNAME(date)

返回date的星期名字。

mysql> select DAYNAME("1998-02-05");  

-> 'Thursday'  

MONTHNAME(date)

返回date的月份名字。

mysql> select MONTHNAME("1998-02-05");  

-> 'February'  

QUARTER(date)

返回date一年中的季度,范围1到4。

mysql> select QUARTER('98-04-01');  

-> 2  

WEEK(date)

WEEK(date,first)

对于星期天是一周的第一天的地方,有一个单个参数,返回date的周数,范围在0到52。2个参数形式WEEK()允许

你指定星期是否开始于星期天或星期一。如果第二个参数是0,星期从星期天开始,如果第二个参数是1,

从星期一开始。

mysql> select WEEK('1998-02-20');  

-> 7  

mysql> select WEEK('1998-02-20',0);  

-> 7  

mysql> select WEEK('1998-02-20',1);  

-> 8  

YEAR(date)

返回date的年份,范围在1000到9999。

mysql> select YEAR('98-02-03');  

-> 1998  

HOUR(time)

返回time的小时,范围是0到23。

mysql> select HOUR('10:05:03');  

-> 10  

MINUTE(time)

返回time的分钟,范围是0到59。

mysql> select MINUTE('98-02-03 10:05:03');  

-> 5  

SECOND(time)

回来time的秒数,范围是0到59。

mysql> select SECOND('10:05:03');  

-> 3  

PERIOD_ADD(P,N)

增加N个月到阶段P(以格式YYMM或YYYYMM)。以格式YYYYMM返回值。注意阶段参数P不是日期值。

mysql> select PERIOD_ADD(9801,2);  

-> 199803  

PERIOD_DIFF(P1,P2)

返回在时期P1和P2之间月数,P1和P2应该以格式YYMM或YYYYMM。注意,时期参数P1和P2不是日期值。

mysql> select PERIOD_DIFF(9802,199703);  

-> 11  

DATE_ADD(date,INTERVAL expr type)

DATE_SUB(date,INTERVAL expr type)

ADDDATE(date,INTERVAL expr type)  

SUBDATE(date,INTERVAL expr type)  

这些功能执行日期运算。对于MySQL 3.22,他们是新的。ADDDATE()和SUBDATE()是DATE_ADD()和DATE_SUB()的同义词。

在MySQL 3.23中,你可以使用+和-而不是DATE_ADD()和DATE_SUB()。(见例子)date是一个指定开始日期的

DATETIME或DATE值,expr是指定加到开始日期或从开始日期减去的间隔值一个表达式,expr是一个字符串;它可以以

一个“-”开始表示负间隔。type是一个关键词,指明表达式应该如何被解释。EXTRACT(type FROM date)函数从日期

中返回“type”间隔。下表显示了type和expr参数怎样被关联: type值 含义 期望的expr格式

  • SECOND 秒 SECONDS

  • MINUTE 分钟 MINUTES

  • HOUR 时间 HOURS

  • DAY 天 DAYS

  • MONTH 月 MONTHS

  • YEAR 年 YEARS

  • MINUTE_SECOND 分钟和秒 “MINUTES:SECONDS”

  • HOUR_MINUTE 小时和分钟 “HOURS:MINUTES”

  • DAY_HOUR 天和小时 “DAYS HOURS”

  • YEAR_MONTH 年和月 “YEARS-MONTHS”

  • HOUR_SECOND 小时, 分钟, “HOURS:MINUTES:SECONDS”

  • DAY_MINUTE 天, 小时, 分钟 “DAYS HOURS:MINUTES”

  • DAY_SECOND 天, 小时, 分钟, 秒 “DAYS HOURS:MINUTES:SECONDS”

MySQL在expr格式中允许任何标点分隔符。表示显示的是建议的分隔符。如果date参数是一个DATE值并且你的计算仅仅

包含YEAR、MONTH和DAY部分(即,没有时间部分),结果是一个DATE值。否则结果是一个DATETIME值。

mysql> SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND;  

-> 1998-01-01 00:00:00  

mysql> SELECT INTERVAL 1 DAY + "1997-12-31";  

-> 1998-01-01  

mysql> SELECT "1998-01-01" - INTERVAL 1 SECOND;  

-> 1997-12-31 23:59:59  

mysql> SELECT DATE_ADD("1997-12-31 23:59:59",  

INTERVAL 1 SECOND);  

-> 1998-01-01 00:00:00  

mysql> SELECT DATE_ADD("1997-12-31 23:59:59",  

INTERVAL 1 DAY);  

-> 1998-01-01 23:59:59  

mysql> SELECT DATE_ADD("1997-12-31 23:59:59",  

INTERVAL "1:1" MINUTE_SECOND);  

-> 1998-01-01 00:01:00  

mysql> SELECT DATE_SUB("1998-01-01 00:00:00",  

INTERVAL "1 1:1:1" DAY_SECOND);  

-> 1997-12-30 22:58:59  

mysql> SELECT DATE_ADD("1998-01-01 00:00:00",  

INTERVAL "-1 10" DAY_HOUR);  

-> 1997-12-30 14:00:00  

mysql> SELECT DATE_SUB("1998-01-02", INTERVAL 31 DAY);  

-> 1997-12-02  

mysql> SELECT EXTRACT(YEAR FROM "1999-07-02");  

-> 1999  

mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03");  

-> 199907  

mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03");  

-> 20102  

如果你指定太短的间隔值(不包括type关键词期望的间隔部分),MySQL假设你省掉了间隔值的最左面部分。例如,

如果你指定一个type是DAY_SECOND,值expr被希望有天、小时、分钟和秒部分。如果你象”1:10″这样指定值,

MySQL假设日子和小时部分是丢失的并且值代表分钟和秒。换句话说,”1:10″ DAY_SECOND以它等价于”1:10″ MINUTE_SECOND

的方式解释,这对那MySQL解释TIME值表示经过的时间而非作为一天的时间的方式有二义性。如果你使用确实不正确的日期,

结果是NULL。如果你增加MONTH、YEAR_MONTH或YEAR并且结果日期大于新月份的最大值天数,日子在新月用最大的天调整。

mysql> select DATE_ADD('1998-01-30', Interval 1 month);  

-> 1998-02-28  

注意,从前面的例子中词INTERVAL和type关键词不是区分大小写的。

TO_DAYS(date)

给出一个日期date,返回一个天数(从0年的天数)。

mysql> select TO_DAYS(950501);  

-> 728779  

mysql> select TO_DAYS('1997-10-07');  

-> 729669  

TO_DAYS()不打算用于使用格列高里历(1582)出现前的值。

FROM_DAYS(N)

给出一个天数N,返回一个DATE值。

mysql> select FROM_DAYS(729669);  

-> '1997-10-07'  

TO_DAYS()

不打算用于使用格列高里历(1582)出现前的值。

DATE_FORMAT(date,format)

根据format字符串格式化date值。下列修饰符可以被用在format字符串中: %M 月名字(January……December)

  • %W 星期名字(Sunday……Saturday)

  • %D 有英语前缀的月份的日期(1st, 2nd, 3rd, 等等。)

  • %Y 年, 数字, 4 位

  • %y 年, 数字, 2 位

  • %a 缩写的星期名字(Sun……Sat)

  • %d 月份中的天数, 数字(00……31)

  • %e 月份中的天数, 数字(0……31)

  • %m 月, 数字(01……12)

  • %c 月, 数字(1……12)

  • %b 缩写的月份名字(Jan……Dec)

  • %j 一年中的天数(001……366)

  • %H 小时(00……23)

  • %k 小时(0……23)

  • %h 小时(01……12)

  • %I 小时(01……12)

  • %l 小时(1……12)

  • %i 分钟, 数字(00……59)

  • %r 时间,12 小时(hh:mm:ss [AP]M)

  • %T 时间,24 小时(hh:mm:ss)

  • %S 秒(00……59)

  • %s 秒(00……59)

  • %p AM或PM

  • %w 一个星期中的天数(0=Sunday ……6=Saturday )

  • %U 星期(0……52), 这里星期天是星期的第一天

  • %u 星期(0……52), 这里星期一是星期的第一天

  • %% 一个文字“%”。

所有的其他字符不做解释被复制到结果中。

mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');  

-> 'Saturday October 1997'  

mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');  

-> '22:23:00'  

mysql> select DATE_FORMAT('1997-10-04 22:23:00',  

'%D %y %a %d %m %b %j');  

-> '4th 97 Sat 04 10 Oct 277'  

mysql> select DATE_FORMAT('1997-10-04 22:23:00',  

'%H %k %I %r %T %S %w');  

-> '22 22 10 10:23:00 PM 22:23:00 00 6'  

MySQL3.23中,在格式修饰符字符前需要%。在MySQL更早的版本中,%是可选的。

TIME_FORMAT(time,format)

这象上面的DATE_FORMAT()函数一样使用,但是format字符串只能包含处理小时、分钟和秒的那些格式修饰符。

其他修饰符产生一个NULL值或0。

CURDATE()

CURRENT_DATE

以’YYYY-MM-DD’或YYYYMMDD格式返回今天日期值,取决于函数是在一个字符串还是数字上下文被使用。

mysql> select CURDATE();  

-> '1997-12-15'  

mysql> select CURDATE() + 0;  

-> 19971215  

CURTIME()

CURRENT_TIME

以’HH:MM:SS’或HHMMSS格式返回当前时间值,取决于函数是在一个字符串还是在数字的上下文被使用。

mysql> select CURTIME();  

-> '23:50:26'  

mysql> select CURTIME() + 0;  

-> 235026  

NOW()

SYSDATE()

CURRENT_TIMESTAMP

以’YYYY-MM-DD HH:MM:SS’或YYYYMMDDHHMMSS格式返回当前的日期和时间,取决于函数是在一个字符串还是在数字的

上下文被使用。

mysql> select NOW();  

-> '1997-12-15 23:50:26'  

mysql> select NOW() + 0;  

-> 19971215235026  

UNIX_TIMESTAMP(date)

如果没有参数调用,返回一个Unix时间戳记(从’1970-01-01 00:00:00’GMT开始的秒数)。如果UNIX_TIMESTAMP()用一

个date参数被调用,它返回从’1970-01-01 00:00:00′ GMT开始的秒数值。date可以是一个DATE字符串、一个DATETIME

字符串、一个TIMESTAMP或以YYMMDD或YYYYMMDD格式的本地时间的一个数字。

mysql> select UNIX_TIMESTAMP();  

-> 882226357  

mysql> select UNIX_TIMESTAMP('1997-10-04 22:23:00');  

-> 875996580  

当UNIX_TIMESTAMP被用于一个TIMESTAMP列,函数将直接接受值,没有隐含的“string-to-unix-timestamp”变换。

FROM_UNIXTIME(unix_timestamp)

以’YYYY-MM-DD HH:MM:SS’或YYYYMMDDHHMMSS格式返回unix_timestamp参数所表示的值,取决于函数是在一个字符串

还是或数字上下文中被使用。

mysql> select FROM_UNIXTIME(875996580);  

-> '1997-10-04 22:23:00'  

mysql> select FROM_UNIXTIME(875996580) + 0;  

-> 19971004222300  

FROM_UNIXTIME(unix_timestamp,format)

返回表示 Unix 时间标记的一个字符串,根据format字符串格式化。format可以包含与DATE_FORMAT()函数列出的条

目同样的修饰符。

mysql> select FROM_UNIXTIME(UNIX_TIMESTAMP(),  

'%Y %D %M %h:%i:%s %x');  

-> '1997 23rd December 03:43:30 x'  

SEC_TO_TIME(seconds)

返回seconds参数,变换成小时、分钟和秒,值以’HH:MM:SS’或HHMMSS格式化,取决于函数是在一个字符串还是在数字

上下文中被使用。

mysql> select SEC_TO_TIME(2378);  

-> '00:39:38'  

mysql> select SEC_TO_TIME(2378) + 0;  

-> 3938  

TIME_TO_SEC(time)

返回time参数,转换成秒。

mysql> select TIME_TO_SEC('22:23:00');  

-> 80580  

mysql> select TIME_TO_SEC('00:39:38');  

-> 2378

MySql修改数据库编码为UTF8避免造成乱码问题

mysql 创建数据库时指定编码很重要,很多开发者都使用了默认编码,乱码问题可是防不胜防。制定数据库的编码可以很大程度上避免倒入导出带来的乱码问题。

网页数据一般采用UTF8编码,而数据库默认为latin 。我们可以通过修改数据库默认编码方式为UTF8来减少数据库创建时的设置,也能最大限度的避免因粗心造成的乱码问题。

我们遵循的标准是,数据库,表,字段和页面或文本的编码要统一起来

我们可以通过命令查看数据库当前编码: mysql> SHOW VARIABLES LIKE ‘character%’;

发现很多对应的都是 latin1,我们的目标就是在下次使用此命令时latin1能被UTF8取代。

第一阶段:

mysql设置编码命令

SET character_set_client = utf8; 
SET character_set_connection = utf8; 
SET character_set_database = utf8; 
SET character_set_results = utf8; 
SET character_set_server = utf8; 

然后 mysql> SHOW VARIABLES LIKE ‘character%’; 你可以看到全变为 utf8 。

但是,这只是一种假象

此种方式只在当前状态下有效,当重启数据库服务后失效。

所以如果想要不出现乱码只有修改my.ini文件,

从my.ini下手(标签下没有的添加,有的修改)

[client] 

default-character-set=utf8 

[mysql] 

default-character-set=utf8 

[mysqld] 

default-character-set=utf8 

以上3个section都要加default-character-set=utf8,平时我们可能只加了mysqld一项。

然后重启mysql,执行

mysql> SHOW VARIABLES LIKE 'character%'; 

确保所有的Value项都是utf8即可。

但是可恶的事情又来了,

|character_set_client | utf8 | 

| character_set_connection | utf8 | 

| character_set_database | utf8 | 

| character_set_filesystem | binary | 

| character_set_results | utf8 | 

| character_set_server | latin1 | 

| character_set_system | utf8 注意 该配置| character_set_server | latin1 无法设置成UTF8 交互时候仍然会出现乱码。

第二阶段:找到下面这东东

X:%path%MySQLMySQL Server 5.0binMySQLInstanceConfig.exe 

重新启动设置,将默认编码设置为utf8.这样就能达到我们所要的效果了。

mysql> SHOW VARIABLES LIKE 'character%'; 

+--------------------------+---------------------------------------------------------+ 

| Variable_name | Value | 

+--------------------------+---------------------------------------------------------+ 

| character_set_client | utf8 | 

| character_set_connection | utf8 | 

| character_set_database | utf8 | 

| character_set_filesystem | binary | 

| character_set_results | utf8 | 

| character_set_server | utf8 | 

| character_set_system | utf8 | 

| character_sets_dir | C:Program FilesMySQLMySQL Server 5.0sharecharsets | 

+--------------------------+---------------------------------------------------------+ 

8 rows in set 

另外注意事项:

1、建表时加utf8,表字段的Collation可加可不加,不加时默认是utf8_general_ci了。

CREATE TABLE `tablename4` ( 
`id` int(11) NOT NULL AUTO_INCREMENT, 
`varchar1` varchar(255) DEFAULT NULL, 
`varbinary1` varbinary(255) DEFAULT NULL, 
PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 

2、网页xxx.php/jsp保存时选择utf8编码,页头最好加上

header('conten-type:text/html;charset=utf-8'); 

在执行CRUD操作前先执行一下

mysql_query("set names utf8"); 

连接数据库设置编码

jdbc:mysql://地址:3306/数据库名?characterEncoding=utf8 

java中的常用编码UTF-8;GBK;GB2312;ISO-8859-1;

对应mysql数据库中的编码utf8;gbk;gb2312;latin1

浅谈MySQL存储引擎选择 InnoDB与MyISAM的优缺点分析

下面先让我们回答一些问题:

  • 你的数据库有外键吗?

  • 你需要事务支持吗?

  • 你需要全文索引吗?

  • 你经常使用什么样的查询模式?

  • 你的数据有多大?

思考上面这些问题可以让你找到合适的方向,但那并不是绝对的。如果你需要事务处理或是外键,那么InnoDB 可能是比较好的方式。如果你需要全文索引,那么通常来说 MyISAM是好的选择,因为这是系统内建的,然而,我们其实并不会经常地去测试两百万行记录。所以,就算是慢一点,我们可以通过使用Sphinx从InnoDB中获得全文索引。

数据的大小,是一个影响你选择什么样存储引擎的重要因素,大尺寸的数据集趋向于选择InnoDB方式,因为其支持事务处理和故障恢复。数据库的在小决定了故障恢复的时间长短,InnoDB可以利用事务日志进行数据恢复,这会比较快。而MyISAM可能会需要几个小时甚至几天来干这些事,InnoDB只需要几分钟。

您操作数据库表的习惯可能也会是一个对性能影响很大的因素。比如: COUNT() 在 MyISAM 表中会非常快,而在InnoDB 表下可能会很痛苦。而主键查询则在InnoDB下会相当相当的快,但需要小心的是如果我们的主键太长了也会导致性能问题。大批的inserts 语句在MyISAM下会快一些,但是updates 在InnoDB 下会更快一些——尤其在并发量大的时候。

所以,到底你检使用哪一个呢?根据经验来看,如果是一些小型的应用或项目,那么MyISAM 也许会更适合。当然,在大型的环境下使用MyISAM 也会有很大成功的时候,但却不总是这样的。如果你正在计划使用一个超大数据量的项目,而且需要事务处理或外键支持,那么你真的应该直接使用InnoDB方式。但需要记住InnoDB 的表需要更多的内存和存储,转换100GB 的MyISAM 表到InnoDB 表可能会让你有非常坏的体验。

MyISAM存储引擎

MyISAM是 默认存储引擎。它基于更老的ISAM代码,但有很多有用的扩展。MyISAM存储引擎的一些特征:

  • 所有数据值先存储低字节。这使得数据机和操作系统分离。二进制轻便性的唯一要求是机器使用补码(如最近20年的机器有的一样)和IEEE浮点格式(在主流机器中也完全是主导的)。唯一不支持二进制兼容性的机器是嵌入式系统。这些系统有时使用特殊的处理器。

  • 先存储数据低字节并不严重地影响速度;数据行中的字节一般是未联合的,从一个方向读未联合的字节并不比从反向读更占用更多的资源。服务器上的获取列值的代码与其它代码相比并不显得时间紧。

  • 大文件(达63位文件长度)在支持大文件的文件系统和操作系统上被支持。

  • 当把删除和更新及插入混合的时候,动态尺寸的行更少碎片。这要通过合并相邻被删除的块,以及若下一个块被删除,就扩展到下一块来自动完成。

  • 每个MyISAM表最大索引数是64。 这可以通过重新编译来改变。每个索引最大的列数是16个。

  • 最大的键长度是1000字节。这也可以通过编译来改变。对于键长度超过250字节的情况,一个超过1024字节的的键块被用上。

  • BLOB和TEXT列可以被索引。

  • NULL值被允许在索引的列中。这个占每个键的0-1个字节。

  • 所有数字键值以高字节为先被存储以允许一个更高地索引压缩。

  • 当记录以排好序的顺序插入(就像你使用一个AUTO_INCREMENT列之时),索引树被劈开以便高节点仅包含一个键。这改善了索引树的空间利用率。

  • 每表一个AUTO_INCREMEN列的内部处理。MyISAM为INSERT和UPDATE操作自动更新这一 列。这使得AUTO_INCREMENT列更快(至少10%)。在序列顶的值被删除之后就不能再利用。(当AUTO_INCREMENT列被定义为多列索 引的最后一列,可以出现重使用从序列顶部删除的值的情况 )。AUTO_INCREMENT值可用ALTER TABLE或myisamch来重置。

  • 如果数据文件中间的表没有自由块了,在其它线程从表读的同时,你可以INSERT新行到表中。(这被认识为并发操作 )。自由块的出现是作为删除行的结果,或者是用比当前内容多的数据对动态长度行更新的结果。当所有自由块被用完(填满),未来的插入又变成并发。

  • 你可以把数据文件和索引文件放在不同目录,用DATA DIRECTORY和INDEX DIRECTORY选项CREATE TABLE以获得更高的速度,请参阅13.1.5节,“CREATE TABLE语法”。

  • 每个字符列可以又不同的字符集。

  • 在MyISAM索引文件里又一个标志,它表明表是否被正确关闭。如果用–myisam-recover选项启动mysqld,MyISAM表在打开得时候被自动检查,如果被表被不恰当地关闭,就修复表。

  • 如果你用–update-state选项运行myisamchk,它标注表为已检查。myisamchk –fast只检查那些没有这个标志的表。

  • myisamchk –analyze为部分键存储统计信息,也为整个键存储统计信息。

  • myisampack可以打包BLOB和VARCHAR列。

MyISAM也支持下列特征:

  • 支持true VARCHAR类型;VARCHAR列以存储在2个字节中的长度来开始。

  • 有VARCHAR的表可以有固定或动态记录长度。

  • VARCHAR和CHAR列可以多达64KB。

  • 一个被搞乱的已计算索引对可对UNIQUE来使用。这允许你在表内任何列的合并上有UNIQUE。(尽管如此,你不能在一个UNIQUE已计算索引上搜索)。

InnoDB存储引擎

InnoDB给MySQL提供 了具有提交,回滚和崩溃恢复能力的事务安全(ACID兼容)存储引擎。InnoDB锁定在行级并且也在SELECT语句提供一个Oracle风格一致的非 锁定读。这些特色增加 了多用户部署和性能。没有在InnoDB中扩大锁定的需要,因为在InnoDB中行级锁定适合非常小的空间。InnoDB也支持FOREIGN KEY强制。在SQL查询中,你可以自由地将InnoDB类型的表与其它MySQL的表的类型混合起来,甚至在同一个查询中也可以混合。

InnoDB是为处理巨大数据量时的最大性能设计。它的CPU效率可能是任何其它基于磁盘的关系数据库引擎所不能匹敌的。

InnoDB存储引擎被完全与MySQL服务器整合,InnoDB存储引擎为在主内存中缓存数据和索引而维持它自己的缓冲池。 InnoDB存储它的表&索引在一个表空间中,表空间可以包含数个文件(或原始磁盘分区)。这与MyISAM表不同,比如在MyISAM表中每个表被存在 分离的文件中。InnoDB 表可以是任何尺寸,即使在文件尺寸被限制为2GB的操作系统上。

InnoDB默认地被包含在MySQL二进制分发中。Windows Essentials installer使InnoDB成为Windows上MySQL的 默认表。

InnoDB被用来在众多需要高性能的大型数据库站点上产生。著名的Internet新闻站点Slashdot.org运行在 InnoDB上。Mytrix, Inc.在InnoDB上存储超过1TB的数据,还有一些其它站点在InnoDB上处理平均每秒800次插入/更新的负荷。

InnoDB和MyISAM的区别

区别概述:

MyISAM 是MySQL中默认的存储引擎,一般来说不是有太多人关心这个东西。决定使用什么样的存储引擎是一个很tricky的事情,但是还是值我们去研究一下,这里的文章只考虑 MyISAM 和InnoDB这两个,因为这两个是最常见的。

下面先让我们回答一些问题:

  • 你的数据库有外键吗?

  • 你需要事务支持吗?

  • 你需要全文索引吗?

  • 你经常使用什么样的查询模式?

  • 你的数据有多大?

思考上面这些问题可以让你找到合适的方向,但那并不是绝对的。如果你需要事务处理或是外键,那么InnoDB 可能是比较好的方式。如果你需要全文索引,那么通常来说 MyISAM是好的选择,因为这是系统内建的,然而,我们其实并不会经常地去测试两百万行记录。所以,就算是慢一点,我们可以通过使用Sphinx从 InnoDB中获得全文索引。

数据的大小,是一个影响你选择什么样存储引擎的重要因素,大尺寸的数据集趋向于选择InnoDB方式,因为其支持事务处理和故障恢复。数据库的在小 决定了故障恢复的时间长短,InnoDB可以利用事务日志进行数据恢复,这会比较快。而MyISAM可能会需要几个小时甚至几天来干这些事,InnoDB 只需要几分钟。

您操作数据库表的习惯可能也会是一个对性能影响很大的因素。比如: COUNT() 在 MyISAM 表中会非常快,而在InnoDB 表下可能会很痛苦。而主键查询则在InnoDB下会相当相当的快,但需要小心的是如果我们的主键太长了也会导致性能问题。大批的inserts 语句在MyISAM下会快一些,但是updates 在InnoDB 下会更快一些——尤其在并发量大的时候。

所以,到底你检使用哪一个呢?根据经验来看,如果是一些小型的应用或项目,那么MyISAM 也许会更适合。当然,在大型的环境下使用MyISAM 也会有很大成功的时候,但却不总是这样的。如果你正在计划使用一个超大数据量的项目,而且需要事务处理或外键支持,那么你真的应该直接使用InnoDB方 式。但需要记住InnoDB 的表需要更多的内存和存储,转换100GB 的MyISAM 表到InnoDB 表可能会让你有非常坏的体验。

区别总结:

  1. InnoDB不支持FULLTEXT类型的索引。

  2. InnoDB 中不保存表的具体行数,也就是说,执行select count() from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count()语句包含 where条件时,两种表的操作是一样的。

  3. 对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引。

  4. DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除。

  5. LOAD TABLE FROM MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用。

另外,InnoDB表的行锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,例如update table set num=1 where name like “%aaa%”

提升InnoDB性能的方法:

MyISAM和InnoDB存储引擎性能差别并不是很大,针对InnoDB来说,影响性能的主要是 innodb_flush_log_at_trx_commit 这个选项,如果设置为1的话,那么每次插入数据的时候都会自动提交,导致性能急剧下降,应该是跟刷新日志有关系,设置为0效率能够看到明显提升,当然,同 样你可以SQL中提交“SET AUTOCOMMIT = 0”来设置达到好的性能。另外,还听说通过设置innodb_buffer_pool_size能够提升InnoDB的性能,但是我测试发现没有特别明显 的提升。

基本上我们可以考虑使用InnoDB来替代我们的MyISAM引擎了,因为InnoDB自身很多良好的特点,比如事务支持、存储 过程、视图、行级锁定等等,在并发很多的情况下,相信InnoDB的表现肯定要比MyISAM强很多,当然,相应的在my.cnf中的配置也是比较关键 的,良好的配置,能够有效的加速你的应用。

任何一种表都不是万能的,只用恰当的针对业务类型来选择合适的表类型,才能最大的发挥MySQL的性能优势。

mysql通过ssl的方式生成秘钥具体生成步骤

— mysql ssl 生成秘钥

1、check ssl是否已经开启

mysql> show variables like '%ssl%'; 

+---------------+----------+ 

| Variable_name | Value | 

+---------------+----------+ 

| have_openssl | DISABLED | 

| have_ssl | DISABLED | 

| ssl_ca | | 

| ssl_capath | | 

| ssl_cert | | 

| ssl_cipher | | 

| ssl_crl | | 

| ssl_crlpath | | 

| ssl_key | | 

+---------------+----------+ 

9 rows in set (0.00 sec) 

2、没有开启,所以打开

在my.cnf末尾端设置ssl 参数, 然后重新启动mysql服务即可

mysql> show variables like '%ssl%'; 

+---------------+-------+ 

| Variable_name | Value | 

+---------------+-------+ 

| have_openssl | YES | 

| have_ssl | YES | 

| ssl_ca | | 

| ssl_capath | | 

| ssl_cert | | 

| ssl_cipher | | 

| ssl_crl | | 

| ssl_crlpath | | 

| ssl_key | | 

+---------------+-------+ 

9 rows in set (0.00 sec) 

3、通过openssl生成证书的配置, 在mysql db server上生成秘钥

mkdir -p /etc/mysql/newcerts/ 

cd /etc/mysql/newcerts/ 

3.1 openssl genrsa 2048 > ca-key.pem

3.2 openssl req -new -x509 -nodes -days 1000 -key ca-key.pem > ca-cert.pem

[root@mysql newcerts]# openssl req -new -x509 -nodes -days 1000 -key ca-key.pem > ca-cert.pem 

You are about to be asked to enter information that will be incorporated 

into your certificate request. 

What you are about to enter is what is called a Distinguished Name or a DN. 

There are quite a few fields but you can leave some blank 

For some fields there will be a default value, 

If you enter '.', the field will be left blank. 

----- 

Country Name (2 letter code) [XX]:ch 

State or Province Name (full name) []:shh 

Locality Name (eg, city) [Default City]:shh 

Organization Name (eg, company) [Default Company Ltd]:xx 

Organizational Unit Name (eg, section) []:db 

Common Name (eg, your name or your server''s hostname) []:mysql.yest.nos 

Email Address []:[email protected] 

3.3 openssl req -newkey rsa:2048 -days 1000 -nodes -keyout server-key.pem > server-req.pem

[root@mysql newcerts]# openssl req -newkey rsa:2048 -days 1000 -nodes -keyout server-key.pem > server-req.pem 

Generating a 2048 bit RSA private key 

.......................................................................................................+++ 

..........................................................+++ 

writing new private key to 'server-key.pem' 

----- 

You are about to be asked to enter information that will be incorporated 

into your certificate request. 

What you are about to enter is what is called a Distinguished Name or a DN. 

There are quite a few fields but you can leave some blank 

For some fields there will be a default value, 

If you enter '.', the field will be left blank. 

----- 

Country Name (2 letter code) [XX]:ch 

State or Province Name (full name) []:shh 

Locality Name (eg, city) [Default City]:ssh 

Organization Name (eg, company) [Default Company Ltd]:xx 

Organizational Unit Name (eg, section) []:db 

Common Name (eg, your name or your server''s hostname) []:mysql.yest.nos 

Email Address []:[email protected] 

Please enter the following 'extra' attributes 

to be sent with your certificate request 

A challenge password []:820923 

An optional company name []:xx 

4、在mysql db server客户端生成ssl文件

4.1 openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem

[root@mysql newcerts]# openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem 

Signature ok 

subject=/C=ch/ST=shh/L=ssh/O=ea/OU=db/CN=mysql.yest.nos/[email protected] 

Getting CA Private Key 

4.2 openssl req -newkey rsa:2048 -days 1000 -nodes -keyout client-key.pem > client-req.pem

[root@mysql newcerts]# openssl req -newkey rsa:2048 -days 1000 -nodes -keyout client-key.pem > client-req.pem 

Generating a 2048 bit RSA private key 

.......+++ 

........................................................+++ 

writing new private key to 'client-key.pem' 

----- 

You are about to be asked to enter information that will be incorporated 

into your certificate request. 

What you are about to enter is what is called a Distinguished Name or a DN. 

There are quite a few fields but you can leave some blank 

For some fields there will be a default value, 

If you enter '.', the field will be left blank. 

----- 

Country Name (2 letter code) [XX]:ch 

State or Province Name (full name) []:shh 

Locality Name (eg, city) [Default City]:shh 

Organization Name (eg, company) [Default Company Ltd]:xx 

Organizational Unit Name (eg, section) []:db 

Common Name (eg, your name or your server''s hostname) []:mysql.yest.nos 

Email Address []:[email protected] 

Please enter the following 'extra' attributes 

to be sent with your certificate request 

A challenge password []:820923 

An optional company name []:xx 

4.3 openssl x509 -req -in client-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > client-cert.pem

[root@mysql newcerts]# openssl x509 -req -in client-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > client-cert.pem 

Signature ok 

subject=/C=ch/ST=shh/L=shh/O=ea/OU=db/CN=mysql.yest.nos/[email protected] 

Getting CA Private Key 

5、[]copy clent.* 3个文件到客户端机器上面/opt/mysql/ssl/去。

6、登陆验证

mysql -uxxx -pxxxx --ssl-ca=/opt/mysql/ssl/ca-cert.pem --ssl-cert=/opt/mysql/ssl/server-cert.pem --ssl-key=/opt/mysql/ssl/server-key.pem 

解析MYSQL显示表信息的方法

在用mysql时(show tables),有时候需要查看表和字段的相关信息(表与某字段是否存在等.)~~而PHP提供了这样的相关函数,如:mysql_list_dbs(),mysql_list_fields(),但mysql_list_fields() 函数等已过时,所以要用show…这个SQL指令来查寻。

SHOW 指令(‘[..]’里的可选)

#显示mysql中所有数据库的名称

show databases;

#显示mysql中的相关表

show tables [ from db_name]

#显示数据表表状态信息

show table status

#查看存储过程状态

show procedure status

#列出表字段完整属性

show full fields from tbl_name

#显示表中列名称

show columns from table_name [ from database_name ] ; 或show columns from database_name.table_name;

#显示一个用户的权限,显示结果类似于grant 命令

show grants for user_name;

#列出表索引

show index from tbl_name

#显示表的索引

show index from table_name

#显示一些系统特定资源的信息,例如,正在运行的线程数量

show status [from   db_name]

#显示系统变量的名称和值

show [ global] variables

#显示系统中正在运行的所有进程,也就是当前正在执行的查询大多数用户可以查看他们自己的进程,但是如果他们拥有process权限,就可以查看所有人的进程,包括密码

show processlist

#显示当前使用或者指定的database中的每个表的信息信息包括表类型和表的最新更新时间

show table status

#显示服务器所支持的不同权限

show privileges

#显示create database 语句是否能够创建指定的数据库

show create database database_name

#显示create database 语句是否能够创建指定的数据库

show create table table_name

#显示安装以后可用的存储引擎和默认引擎

show engies

#显示innoDB存储引擎的状态

show innodb status

#显示BDB存储引擎的日志

show logs   -----这个已经被遗弃了

#显示最后一个执行的语句所产生的错误、警告和通知

show warnings

#只显示最后一个执行语句所产生的错误

show errors

#显示安装后的可用存储引擎和默认引擎

show [storage] engines;

============================================================

mysqlshow,该指令只参显示数据库、表、列的信息

例如:mysqlshow -uroot -pXXXX mysql #显示mysql数据库的信息

例如:mysqlshow -uroot -pXXXX mysql user #显示mysql数据库中user表的信息

例如:mysqlshow -uroot -pXXXX mysql user user #显示mysql数据库中user表中的user列的信息

探讨Mysql中OPTIMIZE TABLE的作用详解

当您的库中删除了大量的数据后,您可能会发现数据文件尺寸并没有减小。这是因为删 除操作后在数据文件中留下碎片所致。Discuz! 在系统数设置界面提供了数据表优化的功能,可以去除删除操作后留下的数据文件碎片,减小文件尺寸,加快未来的读写操作。您只要在做完批量删除,或定期(如 每一两个月)进行一次数据表优化操作即可。

OPTIMIZE TABLE通过制作原来的表的一个临时副本来工作

OPTIMIZE TABLE语法

OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...

如果您已经删除了表的一大部分,或者如果您已经对含有可变长度行的表(含有 VARCHAR, BLOB或TEXT列的表)进行了很多更改,则应使用OPTIMIZE TABLE。被删除的记录被保持在链接清单中,后续的INSERT操作会重新使用旧的记录位置。您可以使用OPTIMIZE TABLE来重新利用未使用的空间,并整理数据文件的碎片。

在多数的设置中,您根本不需要运行OPTIMIZE TABLE。即使您对可变长度的行进行了大量的更新,您也不需要经常运行,每周一次或每月一次即可,只对特定的表运行。

OPTIMIZE TABLE只对MyISAM, BDB和InnoDB表起作用。

对于MyISAM表,OPTIMIZE TABLE按如下方式操作:

  1. 如果表已经删除或分解了行,则修复表。

  2. 如果未对索引页进行分类,则进行分类。

  3. 如果表的统计数据没有更新(并且通过对索引进行分类不能实现修复),则进行更新。

对于BDB表,OPTIMIZE TABLE目前被映射到ANALYZE TABLE上。对于InnoDB表,OPTIMIZE TABLE被映射到ALTER TABLE上,这会重建表。重建操作能更新索引统计数据并释放成簇索引中的未使用的空间。请参见13.5.2.1节,“ANALYZE TABLE语法”。

使用—skip-new或—safe-mode选项可以启动mysqld。通过启动mysqld,您可以使OPTIMIZE TABLE对其它表类型起作用。

注意,在OPTIMIZE TABLE运行过程中,MySQL会锁定表。

OPTIMIZE TABLE语句被写入到二进制日志中,除非使用了自选的NO_WRITE_TO_BINLOG关键词(或其别名LOCAL)。已经这么做了,因此,用于 MySQL服务器的OPTIMIZE TABLE命令的作用相当于一个复制主服务器,在默认情况下,这些命令将被复制到复制从属服务器中。

深入mysql创建自定义函数与存储过程的详解

一、创建自定义函数

在使用mysql的过程中,mysql自带的函数可能不能完成我们的业务需求,这时就需要自定义函数,例如笔者在开发过程中遇到下面这个问题:

mysql表结构如下:

DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `pic` varchar(50) NOT NULL,
  `hashcode` varchar(16) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of test
-- ----------------------------
INSERT INTO `test` VALUES ('1', '2012120910403250c3fa209bf48.jpg', 'bf8f83818080c0f1');
INSERT INTO `test` VALUES ('2', '2012120620430750c092db26557.JPG', 'ff9880f0f680ceff');
INSERT INTO `test` VALUES ('3', '2012120619582550c08861eb062.jpg', '7f7f004f7f7f7c7f');
INSERT INTO `test` VALUES ('4', '2012112911072650b6d16e7f21f.jpg', '7f7f004f7f7f007f');

其中pic字段为图片名称,hashcode是图片的感知哈希编码(16进制编码字符串,长度固定16位),用户输入一个hashcode,怎么从数据库中找出满足字符串对应位置的字符不同的个数小于5的记录呢?就像“11001”和“11101”对应位置不同字符不同的个数为1,比如 用户输入”7f7f004f7f7f00af”,那么第三条和第四条记录是满足的,怎么实现呢?如果单纯的依靠mysql自带的函数很难完成,这时就需要建立自定义函数解决。这个问题的解决在此非常感谢csdn的acmain_chm,acmain_chm以及oschina的@梁小刚,还有@淘宝丁奇

建立自定义函数的过程如下:

1、进入mysql命令行

mysql>

2、用delimiter命令来把语句定界符从 ;变为//。这样就允许在程序体用;定界符传递到服务器,而不是被mysql自己来解释。

mysql> delimiter //

3、创建自定义函数

mysql>CREATE FUNCTION hashDiff( s1 varchar(16), s2 varchar(16)) 
->RETURNS INT
->BEGIN
->DECLARE diff, x INT;
->SET diff =0;
->SET x = 0;
->WHILE (x  < 16 )  DO
->SET x = x+1;
->if SUBSTRING(s1, x,1)<>SUBSTRING(s2, x,1) then
->set diff=diff+ 1;
->end if;
->END WHILE;
->RETURN diff;
->END
->//
mysql>select * from test t where  hashDiff(t.hashcode,'ff9880f0f680ceff')  < 5;

二、创建存储过程

1、进入mysql命令行

mysql>

2、用delimiter命令来把语句定界符从 ;变为//。这样就允许在程序体用;定界符传递到服务器,而不是被mysql自己来解释。

mysql> delimiter //

3、创建存储过程

mysql> delimiter //
mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)
    -> BEGIN
    ->   SELECT COUNT(*) INTO param1 FROM t;
    -> END
    -> //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> CALL simpleproc(@a);
Query OK, 0 rows affected (0.00 sec)


mysql> SELECT @a;
+------+
| @a   |
+------+
| 3    |
+------+
1 row in set (0.00 sec)

深入mysql慢查询设置的详解

在web开发中,我们经常会写出一些SQL语句,一条糟糕的SQL语句可能让你的整个程序都非常慢,超过10秒一般用户就会选择关闭网页,如何优化SQL语句将那些运行时间 比较长的SQL语句找出呢?MySQL给我们提供了一个很好的功能,那就是慢查询!所谓的慢查询就是通过设置来记录超过一定时间的SQL语句!那么如何应用慢查询呢?

1. 开启MySQL的慢查询日志功能

默认情况下,MySQL是不会记录超过一定执行时间的SQL语句的。要开启这个功能,我们需要修改MySQL的配置文件,windows下修改my.ini,Linux下修改my.cnf文件,在[mysqld]最后增加如下命令:

slow_query_log
long_query_time = 1

2. 测试慢查询日志功能

(1)进入MySql控制台,执行如下语句:

select sleep(2);
mysql> select sleep(2);

+----------+

| sleep(2) |

+----------+

|        0 |

+----------+

1 row in set (2.12 sec)

(2)查看慢查询日志文件think-slow.log,在文件最后发现:

# Time: 121120 20:06:23
# User@Host: root[root] @ localhost [127.0.0.1]
# Query_time: 2.104120  Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 0
SET timestamp=1353413183;
select sleep(2);

3. 解释

(1)slow_query_log 这句是开启记录慢查询功能,slow_query_log=0关闭;slow_query_log=1开启(这个1可以不写)

(2)long_query_time = 1 这句是记录超过1秒的SQL执行语句

(3)那么这个日志文件存放在什么地方呢?

默认是放在mysql的data目录,并且文件名为host_name-slow.log即 主机名-slow.log,比如在笔者的开发机上就是THINK-slow.log(因为偶用的Thinkpad,呵呵)

(4)如果日志文件不想放在data目录,我们可以通过如下配置指定存放的目录及日志文件名:

slow_query_log_file=file_name

其中file_name就是你的存放日志的目录和文件名,在这里注意有的资料上可能是log-slow-queries=file_name,这个在mysql5.5版已经过时!

4. 如何记录低于1s的慢查询记录呢?

MySQL5.21版以前long_query_time 参数的单位是秒,默认值是10。这相当于说最低只能记录执行时间超过 1 秒的查询,怎么记录查询时间超过100毫秒的SQL语句记录呢?在mysql5.21+后版本支持毫秒记录

(1)进入MySql控制台,运行如下sql语句:

set global long_query_time=0.1

该句是设置记录慢查询超过时间100ms的SQL,记住要重启mysql才能生效!

(2)测试

进入mysql控制台,执行如下sql语句:

select sleep(0.5);

查看慢查询日志文件,我们看到最后添加的新信息:

# Time: 121120 20:42:06
# User@Host: root[root] @ localhost [127.0.0.1]
# Query_time: 0.500028  Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 0
SET timestamp=1353415326;
select sleep(0.5);

如何使用索引提高mysql查询速度

一、前言

在web开发中,页面模板,业务逻辑(包括缓存、连接池)和数据库这三个部分,数据库在其中负责执行SQL查询并返回查询结果,是影响网站速度最重要的性能瓶颈。本文主要针对MySql数据库,双十一的电商大战,引发了淘宝技术热议,而淘宝现在去IOE(I代表IBM的缩写,即去IBM的存储设备和小型机;O是代表Oracle的缩写,也即去Oracle数据库,采用MySQL和Hadoop替代的解决方案,;E是代表EMC2,即去EMC2的设备性,用PC Server替代EMC2),大量采用MySql集群!让MySql再次成为耀眼的明星!而优化数据的重要一步就是索引的建立,对于mysql中出现的慢查询,我们可以通过使用索引来提升查询速度。索引用于快速找出在某个列中有一特定值的行。不使用索引,MySQL将进行全表扫描,从第1条记录开始然后读完整个表直到找出相关的行。

二、mysql索引类型及创建

常用的索引类型有

1、主键索引

它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引:

CREATE TABLE user(
id int unsigned not null auto_increment,
name varchar(50) not null,
email varchar(40) not null,
primary key (id)
); 

2、普通索引

这是最基本的索引,它没有任何限制。创建方式:

create index idx_name on user(
name(20)
); 

mysql支持前缀索引,一般姓名不会超过20个字符,所以我们这里建立索引的时候限定了长度20,这样可以节省索引文件大小

3、唯一索引

它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。创建方式:

CREATE UNIQUE INDEX idx_email ON user(
email
); 

4、全文索引

MySQL支持全文索引和搜索功能。MySQL中的全文索引类型为FULLTEXT的索引。 FULLTEXT 索引仅可用于 MyISAM表;

CREATE TABLE articles (
   id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
   title VARCHAR(200),
   body TEXT,
   FULLTEXT (title,body)
    );

mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST (‘database’);

查询结果:

+----+-------------------+------------------------------------------+

| id | title             | body                                     |

+----+-------------------+------------------------------------------+

|  5 | MySQL vs. YourSQL | In the following database comparison ... |

|  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |

+----+-------------------+------------------------------------------+

2 rows in set (0.00 sec)

MATCH()函数对于一个字符串执行资料库内的自然语言搜索。一个资料库就是1套1个或2个包含在FULLTEXT内的列。搜索字符串作为对AGAINST()的参数而被给定。对于表中的每一行, MATCH() 返回一个相关值,即, 搜索字符串和 MATCH()表中指定列中该行文字之间的一个相似性度量。

5、复合索引

CREATE TABLE test (
    id INT NOT NULL,
    last_name CHAR(30) NOT NULL,
    first_name CHAR(30) NOT NULL,
    PRIMARY KEY (id),
    INDEX name (last_name,first_name)
);

name索引是一个对last_name和first_name的索引。索引可以用于为last_name,或者为last_name和first_name在已知范围内指定值的查询。因此,name索引用于下面的查询:

SELECT * FROM test WHERE last_name='Widenius';

SELECT * FROM test WHERE last_name='Widenius' AND first_name='Michael';

但是不能用于SELECT * FROM test WHERE first_name=’Michael’;这是因为MySQL组合索引为“最左前缀”的结果,简单的理解就是只从最左面的开始组合。

三、在什么情况下使用索引

1、为搜索字段建索引,如果在你的表中,某个字段你经常用来做搜索,那么,请为其建立索引吧。一般来说,在WHERE和JOIN中出现的列需要建立索引以提高查询速度。

例如从fps表(表中有name字段)中检索姓名为”李武”的人,

下面用explain来解释执行建立索引和未建立索引的区别:

a.未建立索引前

explain select name from fps where name="李武";

未分类

[SQL] select name from fps where name=”李武”;

影响的数据栏: 0

时间: 0.003ms

b.建立索引后

create index idx_name on fps(
name
);

explain select name from fps where name=”李武”;

未分类

[SQL] select name from fps where name=”李武”;

影响的数据栏: 0

时间: 0.001ms

2、下面我们就来看看这个EXPLAIN分析结果的含义。

table:这是表的名字。

type:连接操作的类型。下面是MySQL文档关于ref连接类型的说明:

“对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是

UNIQUE或PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话),则使用ref。如果使用的键仅仅匹配少量行,该联接

类型是不错的。” 在本例中,由于索引不是UNIQUE类型,ref是我们能够得到的最好连接类型。 如果EXPLAIN显示连接类型是“ALL”,而且你并不想从表里面选择出大多数记录,那么MySQL的操作效率将非常低,因为它要扫描整个表。你可以加入更多的索引来解决这个问题。预知更多信息,请参见MySQL的手册说明。

possible_keys:

可能可以利用的索引的名字。这里的索引名字是创建索引时指定的索引昵称;如果索引没有昵称,则默认显示的是索引中第一个列的名字

(在本例中,它是“idx_name”)。

Key:

它显示了MySQL实际使用的索引的名字。如果它为空(或NULL),则MySQL不使用索引。

key_len:

索引中被使用部分的长度,以字节计。

ref:

它显示的是列的名字(或单词“const”),MySQL将根据这些列来选择行。在本例中,MySQL根据三个常量选择行。

rows:

MySQL所认为的它在找到正确的结果之前必须扫描的记录数。显然,这里最理想的数字就是1。 本例中未索引前遍历的记录数为1041,而建立索引后为1

Extra:

这里可能出现许多不同的选项,其中大多数将对查询产生负面影响。在本例中,MySQL只是提醒我们它将用using where,using index子句限制搜索结果集。

四、最常用的存储引擎

1、Myisam存储引擎:每个Myisam在磁盘上存储成三个文件。文件名都和表名相同,扩展名分别为.frm(存储表定义)、.MYD(存储数据)、.MYI(存储索引)。数据文件和索引文件可以放置在不同目录,平均分布io,获得更快的速度。对存储大小没有限制,MySQL数据库的最大有效表尺寸通常是由操作系统对文件大小的限制决定的,

2、InnoDB存储引擎:具有提交、回滚、奔溃恢复能力的事务安全。与Myisam相比,InnoDB的写效率差一些并且会占用更多的磁盘空间以保留数据和索引。

3、如何选择合适的引擎

下面是常用存储引擎适用的环境:

Myisam:它是在Web、数据仓储和其他应用环境下最常使用的存储引擎;

InnoDB:用于事务处理应用程序,具有更多特性,包括ACID事务特性。

mysql中event的用法详解

一、基本概念

mysql5.1版本开始引进event概念。event既“时间触发器”,与triggers的事件触发不同,event类似与linux crontab计划任务,用于时间触发。通过单独或调用存储过程使用,在某一特定的时间点,触发相关的SQL语句或存储过程。

二、适用范围

对于每隔一段时间就有固定需求的操作,如创建表,删除数据等操作,可以使用event来处理。

例如:使用event在每月的1日凌晨1点自动创建下个月需要使用的三张表。

三、使用权限

单独使用event调用SQL语句时,查看和创建需要用户具有event权限,调用该SQL语句时,需要用户具有执行该SQL的权限。Event权限的设置保存在mysql.user表和mysql.db表的Event_priv字段中。

当event和procedure配合使用的时候,查看和创建存储过程需要用户具有create routine权限,调用存储过程执行时需要使用excute权限,存储过程调用具体的SQL语句时,需要用户具有执行该SQL的权限。

查看EVENT命令有如下几种:

(1)查询mysql.event表;

(2)通过SHOW EVENTS命令;

(3)通过SHOW FULL EVENTS命令;

(4)通过查询information_schema.events表

(5)SHOW CREATE EVENT。

总之,event的使用频率较低建议使用root用户进行创建和维护。

四、基本语法

4.1 开启定时器

要使event起作用,MySQL的常量GLOBAL event_scheduler必须为on或者是1。

— 查看是否开启定时器

SHOW VARIABLES LIKE 'event_scheduler';

— 开启定时器 0:off 1:on

SET GLOBAL event_scheduler = 1; 

当你设定事件计划为0 或OFF,即关闭事件计划进程的时候,不会有新的事件执行,但现有的正在运行的事件会执行到完毕

对于我们线上环境来说,使用event时,注意在主库上开启定时器,从库上关闭定时器,event触发所有操作均会记录binlog进行主从同步,从库上开启定时器很可能造成卡库。切换主库后之后记得将新主库上的定时器打开。

请特别注意!

4.2 创建事件

CREATE EVENT 的语法如下:

CREATE EVENT

[IF NOT EXISTS] ---------------------------------------------*标注1

event_name -----------------------------------------------------*标注2

ON SCHEDULE schedule ------------------------------------*标注3 

[ON COMPLETION [NOT] PRESERVE] -----------------*标注4

[ENABLE | DISABLE] ----------------------------------------*标注5 

[COMMENT 'comment'] --------------------------------------*标注6 

DO sql_statement -----------------------------------------------*标注7

说明:

标注1:[IF NOT EXISTS]

使用IF NOT EXISTS,只有在同名event不存在时才创建,否则忽略。建议不使用以保证event创建成功。

标注2:event_name

名称最大长度可以是64个字节。名字必须是当前Dateabase中唯一的,同一个数据库不能有同名的event。

使用event常见的工作是创建表、插入数据、删除数据、清空表、删除表。

为了避免命名规范带来的不便,最好让事件名称具有描述整个事件的能力。建议命名规则如下为:动作名称(INTO/FROM)表名_TIME,例如:

1、每月创建(清空/删除)fans表:

create(truncate/drop)_table_fans_month;

2、每天从fans表插入(删除)数据:

insert(delete)_into(from)_fans_day;

标注3:ON SCHEDULE

ON SCHEDULE 计划任务,有两种设定计划任务的方式:

1、AT 时间戳,用来完成单次的计划任务。

2、EVERY 时间(单位)的数量时间单位[STARTS 时间戳] [ENDS时间戳],用来完成重复的计划任务。

在两种计划任务中,时间戳可以是任意的TIMESTAMP 和DATETIME 数据类型,时间戳需要大于当前时间。

在重复的计划任务中,时间(单位)的数量可以是任意非空(Not Null)的整数式,时间单位是关键词:YEAR,MONTH,DAY,HOUR,MINUTE 或者SECOND。

提示: 其他的时间单位也是合法的如:QUARTER, WEEK, YEAR_MONTH,DAY_HOUR,DAY_MINUTE,DAY_SECOND,HOUR_MINUTE,HOUR_SECOND, MINUTE_SECOND,不建议使用这些不标准的时间单位。

标注4: [ON COMPLETION [NOT] PRESERVE]

ON COMPLETION参数表示”当这个事件不会再发生的时候”,即当单次计划任务执行完毕后或当重复性的计划任务执行到了ENDS阶段。而PRESERVE的作用是使事件在执行完毕后不会被Drop掉,建议使用该参数,以便于查看EVENT具体信息。

标注5:[ENABLE | DISABLE]

参数Enable和Disable表示设定事件的状态。Enable表示系统将执行这个事件。Disable表示系统不执行该事件。

可以用如下命令关闭或开启事件:

ALTER EVENT event_name  ENABLE/DISABLE

标注6:[COMMENT ‘comment’]

注释会出现在元数据中,它存储在information_schema表的COMMENT列,最大长度为64个字节。’comment’表示将注释内容放在单引号之间,建议使用注释以表达更全面的信息。

标注 7: DO sql_statement

DO sql_statement字段表示该event需要执行的SQL语句或存储过程。这里的SQL语句可以是复合语句,例如:

BEGIN

CREATE TABLE test1;//创建表(需要测试一下)

DROP TABLE test2;//删除表

CALL proc_test1();//调用存储过程

END

使用BEGIN和END标识符将复合SQL语句按照执行顺序放在之间。当然SQL语句是有限制的,对它的限制跟函数Function和触发器Trigger 中对SQL语句的限制是一样的,如果你在函数Function 和触发器Trigger 中不能使用某些SQL,同样的在EVENT中也不能使用。明确的来说有下面几个:

LOCK TABLES

UNLOCK TABLES

CREATE EVENT

ALTER EVENT

LOAD DATA

4.3 执行逻辑

  • For (已建立事件each event that has been created)

  • If (事件的状态非DISABLE)

  • And (当前时间在ENDS时间之前)

  • And (当前时间在STARTS时间之后)

  • And (在上次执行后经过的时间)

  • And (没有被执行)

Then:

  • 建立一个新的线程

  • 传递事件的SQL语句给新的线程

(该线程在执行完毕后会自动关闭)

4.4 修改事件

使用ALTER EVENT 来修改事件,具体的ALTER语法如下,与创建事件的语法类似:

ALTER EVENT

event_name

ON SCHEDULE schedule

[RENAME TO new_event_name]

[ON COMPLETION [NOT] PRESERVE]

[ENABLE | DISABLE]

[COMMENT 'comment']

DO sql_statement

4.5 删除事件

EVENT使用DROP EVENT语句来删除已经创建的事件,语法如下:

DROP EVENT

[IF EXISTS]

event_name

但当一个事件正在运行中时,删除该事件不会导致事件停止,事件会执行到完毕为止。使用DROP USER和DROP DATABASE 语句同时会将包含其中的事件删除。

五、常用实例

每隔一秒自动调用e_test()存储过程

CREATE EVENT IF NOT EXISTS e_test
ON SCHEDULE EVERY 1 SECOND
ON COMPLETION PRESERVE
DO CALL e_test();

每个月的一号凌晨1 点执行STAT()存储过程:

CREATE  EVENT  NOT EXISTS  STAT
ON  SCHEDULE  EVERY  1  MONTH  STARTS DATE_ADD(DATE_ADD(DATE_SUB(CURDATE(),INTERVAL DAY(CURDATE())-1 DAY), INTERVAL 1 MONTH),INTERVAL 1 HOUR)
ON  COMPLETION  PRESERVE  ENABLE
DO
BEGIN
CALL STAT();
END