什么是MySql数据库
MySql数据库是开放源代码的关系型数据库。目前,它可以提供的功能有:支持sql语言、子查询、存储过程、触发器、视图、索引、事务、锁、外键约束和影像复制等。同Oracle 和SQL Server等大型数据库系统一样,MySql也是客户/服务器系统并且是单进程多线程架构的数据库。并且MySQL是一个真正的多用户、多线程SQL数据库服务器。MySQL的客户机/服务器结构由一个服务器守护程序mysql和很多不同的客户程序和库组成。由于其源码的开放性及稳定性,且与网站流行编徎语言PHP的完美结合,现在很多站点都利用其当作后端数据库,使其获得了广泛应用。MySql区别于其它数据库系统的一个重要特点是支持插入式存储引擎。
那么什么是存储引擎呢?
存储引擎说白了就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。因为在关系数据库中数据的存储是以表的形式存储的,所以存储引擎也可以称为表类型(即存储和操作此表的类型)。在Oracle 和SQL Server等数据库中只有一种存储引擎,所有数据存储管理机制都是一样的。而MySql数据库提供了多种存储引擎。用户可以根据不同的需求为数据表选择不同的存储引擎,用户也可以根据自己的需要编写自己的存储引擎。
MySql中有哪些存储引擎?
1. MyISAM:这种引擎是MySql最早提供的, 这种引擎又可以分为静态MyISAM、动态MyISAM 和压缩MyISAM三种:
静态MyISAM:如果数据表中的各数据列的长度都是预先固定好的,服务器将自动选择这种表类型。因为数据表中每一条记录所占用的空间都是一样的,所以这种表存取和更新的效率非常高。当数据受损时,恢复工作也比较容易做。
动态MyISAM:如果数据表中出现varchar、xxxtext或xxxBLOB字段时,服务器将自动选择这种表类型。相对于静态MyISAM,这种表存储空间比较小,但由于每条记录的长度不一,所以多次修改数据后,数据表中的数据就可能离散的存储在内存中,进而导致执行效率下降。同时,内存中也可能会出现很多碎片。因此,这种类型的表要经常用optimize table命令或优化工具来进行碎片整理。
压缩MyISAM:以上说到的两种类型的表都可以用myisamchk工具压缩。这种类型的表进一步减小了占用的存储,但是这种表压缩之后不能再被修改。另外,因为是压缩数据,所以这种表在读取的时候要先时行解压缩。
但是,不管是何种MyISAM表,目前它都不支持事务,行级锁和外键约束的功能。
2 MyISAM Merge引擎:这种类型是MyISAM类型的一种变种。合并表是将几个相同的MyISAM表合并为一个虚表。常应用于日志和数据仓库。
3 InnoDB:InnoDB表类型可以看作是对MyISAM的进一步更新产品,它提供了事务、行级锁机制和外键约束的功能。
4 memory(heap):这种类型的数据表只存在于内存中。它使用散列索引,所以数据的存取速度非常快。因为是存在于内存中,所以这种类型常应用于临时表中。
5 archive:这种类型只支持select 和 insert语句,而且不支持索引。常应用于日志记录和聚合分析方面。
当然MySql支持的表类型不止上面几种。 下面介绍如何查看和设置数据表类型。
MySql中关于存储引擎的操作:
1查看数据库可以支持的存储引擎:show engines,默认数据表类型是MyISAM。当然,我们可以通过修改数据库配置文件中的选项,设定默认表类型。
2.通过显示表的创建语句可以查看该表的Engine, Showcreate table tablename;
3 设置或修改表的存储引擎,在创建表的语句上加上engine=engineName即可,如:
而修改存储引擎,使用alter命令,很容易想到,因为Engine是在创建表的时候定好的,顾使用alter来修改,可以用命令Altertable tableName engine =engineName
假如,若需要将表user的存储问引擎修改为archive类型,则可使用命令alter table userengine=archive。
聚集索引
聚集索引确定表中数据的物理顺序。聚集索引类似于电话簿,后者按姓氏排列数据。由于聚集索引规定数据在表中的物理存储顺序,因此一个表只能包含一个聚集索引。但该索引可以包含多个列(组合索引),就像电话簿按姓氏和名字进行组织一样。
聚集索引对于那些经常要搜索范围值的列特别有效。使用聚集索引找到包含第一个值的行后,便可以确保包含后续索引值的行在物理相邻。例如,如果应用程序执行 的一个查询经常检索某一日期范围内的记录,则使用聚集索引可以迅速找到包含开始日期的行,然后检索表中所有相邻的行,直到到达结束日期。这样有助于提高此类查询的性能。同样,如果对从表中检索的数据进行排序时经常要用到某一列,则可以将该表在该列上聚集(物理排序),避免每次查询该列时都进行排序,从而节 省成本。 当索引值唯一时,使用聚集索引查找特定的行也很有效率。例如,使用唯一雇员 ID 列 emp_id 查找特定雇员的最快速的方法,是在 emp_id 列上创建聚集索引或 PRIMARY KEY 约束
My SQL常用目录及系统命令
1、数据库默认目录 /var/lib/mysql/,为啥放在这个地方?一般var下面是最大的目录,数据文件也存储在这个地方,如果要想修改数据文件目录,要配置文件进行修改,有几个地方要进行修改 (1)在配置文件中mysql.sock文件产生的位置,mysql.sock文件的产生位置,如socket = /home/data/mysql/mysql.sock (2)修改mysql的启动脚本中的datadir:init.d/myql:datadir=/home/data/mysql需要注意的有要将默认路径下的data文件copy到新目录而不是新建,还有要将Mysql的一份配置文件copy到/etc/下面,对sock位置的修改要在改文件下修改,最后在修改前停止mysql, 修改完进行生效重启Mysql.
2、配置文件 /usr/share/mysql(mysql.server命令及配置文件),如/usr/share/mysql/my-medium.cnf
3、相关命令 /usr/bin(mysqladminmysqldump等命令) 命令在/usr/bin下
4、启动脚本 /etc/rc.d/init.d/mysql(启动脚本文件mysql的目录)
5、自动启动:只要记住关于自动启动的都在/sbin/chkconfig就可以了
1)察看mysql是否在自动启动列表中 [root@test1local]# /sbin/chkconfig –list
2)把MySQL添加到系统启动服务组里面去 [root@test1local]# /sbin/chkconfig –add mysql
3)把MySQL从启动服务组里面删除。[root@test1 local]# /sbin/chkconfig –del mysql
6、停掉与启动Mysql命令:mysqladmin -u root -pshutdown 和 /etc/rc.d/init.d/mysql start
Sql命令中的几个关键字
(1) Group by使用, 比如delete from tablename where id not in (select max(id) from tablenamegroup by col1,col2,...) 《= 删除重复数据的例子, Group By的含义是进行分组值相同的为一组,注意使用Group By 之后 Select 出来的列必须只能来自于group By 或使用聚合函数Sum, AVG, max, min等中的列:返回集字段中,这些字段要么就要包含在Group By语句的后面,作为分组的依据;要么就要被包含在聚合函数中,GroupBy与聚合函数一块使用,表示对分组后的数据进行求和,平均,最大值等。
(2) Group By 和 Having, Where ,Order by语句的执行顺序:以尽可能的减少操纵的数据为原则,显然顺序为:Where, Group By, Having, Order by,首先where将最原始记录中不满足条件的记录筛选,减少分组数据,然后Group By与Having显然是Having是基于Groupby的,顾Having在Groupby之后,而Order By在Groupby和where之前都没用用,只有在Groupby之后才起作用,顾最后。
(3) Having 的使用:Having对Group By进行限定条件,可以使用聚合函数和Groupby中的列。
(4) Left outer join 与 left inner join的区别:外连接可以包含主表的全部行,而内连接只含有匹配那行
(5) Distinct 用法,去掉重复行,类似于Linux命令中的uniq,但uniq命令只能去掉相邻的重复行,所以在用之前要进行sort
(6) SQL Sever中用法: sysobjects和syscolumns表放了数据库中的所有表名和一个表的列名,而在My SQL中使用:show tables
MySql命令
(1) Mysql的所有用户都在user表中,可以通过该表进行,增加用户,修改用户密码,删除用户,和赋予用户权限等,注意修改后要使用FLUSH PRIVILEGES进行确认,如下:
删除匿名用户:delete from User where User=""; 匿名用户的User是空
增加一个用户 INSERT INTO mysql.user (Host,User,Password) VALUES ('%','system', PASSWORD('manager'));
修改密码update User set Password=PASSWORD(newpassword) where User=root;
(1) 用Grant 命令授权,输入的代码如下:
grant select,insert,update on mydb.*to NewUserName@HostNameidentified by"password"; 如果对HostName不限制,则使用%
(2) 对用户的每一项权限进行设置: 如:
mysql>INSERT INTO user VALUES('localhost','system',PASSWORD('manager'), 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y'); 对于3.22.34版本的MySQL,这里共14个"Y",其相应的权限如下(按字段顺序排列):
权限
表列名称
相应解释
使用范围
select
Select_priv
只有在真正从一个表中检索时才需要select权限
表
insert
Insert_priv
允许您把新行插入到一个存在的表中
表
update
Update_priv
允许你用新值更新现存表中行的列
表
delete
Delete_priv
允许你删除满足条件的行
表
create
Create_priv
允许你创建新的数据库和表
数据库、表或索引
drop
Drop_priv
抛弃(删除)现存的数据库和表
数据库或表
reload
Reload_priv
允许您告诉服务器再读入授权表
服务器管理
shutdown
Shutdown_priv
可能被滥用(通过终止服务器拒绝为其他用户服务)
服务器管理
process
Process_priv
允许您察看当前执行的查询的普通文本,包括设定或改变口令查询
服务器管理
file
File_priv
权限可以被滥用在服务器上读取任何可读的文件到数据库表
服务器上文件存取
grant
Grant_priv
允许你把你自己拥有的那些权限授给其他的用户
数据库或表
references
References_priv
允许你打开和关闭记录文件
数据库或表
index
Index_priv
允许你创建或抛弃(删除)索引
表
alter
Alter_priv
允许您改变表格,可以用于通过重新命名表来推翻权限系统
表
对上面的14中权限,可以分为两种全局管理权限和数据表权限
全局管理权限:
FILE: 在MySQL服务器上读写文件。
PROCESS: 显示或杀死属于其它用户的服务线程。
RELOAD: 重载访问控制表,刷新日志等。
SHUTDOWN: 关闭MySQL服务。
数据库/数据表/数据列权限:
ALTER: 修改已存在的数据表(例如增加/删除列)和索引。
CREATE: 建立新的数据库或数据表。
DELETE: 删除表的记录。
DROP: 删除数据表或数据库。
INDEX: 建立或删除索引。
INSERT: 增加表的记录。
SELECT: 显示/搜索表的记录。
UPDATE: 修改表中已存在的记录。
特别的权限:
ALL: 允许做任何事(和root一样)。
USAGE: 只允许登录--其它什么也不允许做。
(2) 查看所有用show命令,查看当前用select函数
查看所有的数据库Show databases
创建和删除数据库create/drop database name
使用或连接数据库use databasename(),
查看当前使用的数据库:select database()
查询当前时间:selectnow()
查询当前用户:select user()
查询数据库版本:select version()
查看所有表:show tables
show processlist;列出每一笔联机的信息。
show variables;列出mysql的系统设定。
show tables from db_name;列出db_name中所有数据表;
show [full] columns from table_name;列出table_name中完整信息,如栏名、类型,包括字符集编码。
show index from table_name; 列出table_name中所有的索引。
show table status;;列出当前数据库中数据表的信息。
show table status from db_name;;列出当前db_name中数据表的信息。
alter table table_name engine innodb|myisam|memory ;更改表类型
explain table_name / describe table_name ; 列出table_name完整信息,如栏名、类型。
show create table table_name 显示当前表的建表语句
alter table table_name add primary key (picid) ; 向表中增加一个主键
alter table table_name add column userid int after picid 修改表结构增加一个新的字段
alter table table_name character set gb2312 改变表的编码
select user(); 显示当前用户。
select password(’root’); 显示当前用户密码
select now(); 显示当前日期
flush privileges 在不重启的情况下刷新用户权限
mysqld –default-character-set=gb2312 ;设置默认字符集为gb2312
(3) 表操作
备注:操作之前使用“use<数据库名>”应连接某个数据库。
匹配字符:可以用通配符_代表任何一个字符,%代表任何字符串;
联合字符或者多个列(将列id与":"和列name和"="连接)
select concat(id,':',name,'=') fromstudents;
limit(选出10到20条)<第一个记录集的编号是0>,SQLServer上为Top
select * from students order by id limit 9,10;
建表:create table <表名> (<字段名 1> <类型 1> [,..<字段名 n><类型 n>]);
插入数据:insert into <表名> [( <字段名 1>[,..<字段名 n >])] values ( 值 1 )[, ( 值 n )]
获取表结构:describe tablename, desc tablename, show columns from tablename
删除表 drop table tablename
删除表中数据 命令:delete from 表名 where 表达式
修改表中数据 命令:update 表名 set 字段=新值,... where 条件
在表中增加字段 命令:alter table 表名 add 字段 类型 其他;
更改表名 命令:rename table 原表名 to 新表名
更新字段内容 命令:update 表名 set 字段名 = 新内容,
删除student_course数据库中的students数据表:rm-f student_course/students.* 直接使
用linux命令来删除,也可以使用drop命令
创建临时表:create temporary table zengchao(name varchar(10));
创建表是先判断表是否存在: create table ifnot exists students(……);
从已经有的表中复制表的结构: create table table2 select * from table1 where 1<>1;
复制表,复制表的时候也会将表结构也复制过去了:create table table2 select * from table1;
对表重新命名:altertable table1 rename as table2;
创建索引,创建索引有两种方式,alter原来的表结构然后add,或者create index on
altertable table1 add index ind_id (id);
createindex ind_id on table1 (id);
createunique index ind_id on table1 (id);//建立唯一性索引
删除索引drop index idx_id on table1;
alter table table1 dropindex ind_id;
可以使用ALTER TABLE语句来更新与属性或表有关的约束。关于修改索引也是用类似的命令
删除约束:ALTER TABLEDROP CONSTRAINT约束名
增加约束ALTER TABLEADD CONSTRAINT约束名约束定义
(4) 数据库导入导出
从数据库导出数据库文件, 使用“mysqldump”命令
从外部文件导入数据库中
MySQL命令应用:
(1) mysql之删除重复数据,删除id重复的数据
delete person as a from person as a,
(
select *,min(id) from person group by id having count(1)> 1
) as b
where a.id = b.id
(2) 查找重复的,并且除掉最小的那个
delete tb_person as a from tb_person as a,
(
select *,min(id) from tb_person group by name having count(1) > 1
) as b
where a.name = b.name and a.id > b.id;
MySql explain优化SQL语句
在mysql version 4.1中,explain输出的结果格式改变了,使得它更适合例如 union语句、子查询以及派生表的结构。更令人注意的是,它新增了2个字段: id和 select_type。当你使用早于mysql4.1的版本就看不到这些字段了。
explain结果的每行记录显示了每个表的相关信息,每行记录都包含以下几个字段:
(1) id : 本次 select 的标识符。在查询中每个 select都有一个顺序的数值。
(2) select_type:select 的类型,可能会有以下几种:
(3) table:记录查询引用的表。
(4) type:表连接类型。以下列出了各种不同类型的表连接,依次是从最好的到最差的:
(5) possible_keys:possible_keys字段是指 mysql在搜索表记录时可能使用哪个索引。注意,这个字段完全独立于explain 显示的表顺序。这就意味着 possible_keys里面所包含的索引可能在实际的使用中没用到。如果这个字段的值是null,就表示没有索引被用到。这种情况下,就可以检查 where子句中哪些字段那些字段适合增加索引以提高查询的性能。就这样,创建一下索引,然后再用explain 检查一下。想看表都有什么索引,可以通过 show index from tbl_name来看。
(6) key:key字段显示了mysql实际上要用的索引。当没有任何索引被用到的时候,这个字段的值就是null。想要让mysql强行使用或者忽略在 possible_keys字段中的索引列表,可以在查询语句中使用关键字force index,use index,或 ignore index。如果是 myisam 和 bdb 类型表,可以使用 analyzetable 来帮助分析使用使用哪个索引更好。如果是 myisam类型表,运行命令 myisamchk --analyze也是一样的效果。
(7) key_len:key_len 字段显示了mysql使用索引的长度。当 key 字段的值为 null时,索引的长度就是 null。注意,key_len的值可以告诉你在联合索引中mysql会真正使用了哪些索引。
(8) ref:ref 字段显示了哪些字段或者常量被用来和 key配合从表中查询记录出来。
(9) rows:rows 字段显示了mysql认为在查询中应该检索的记录数。
(10) extra:本字段显示了查询中mysql的附加信息。以下是这个字段的几个不同值的解释:
使用explain优化SQL实例
通过 explain 的结果中 rows字段的值的乘积大概地知道本次连接表现如何。它可以粗略地告诉我们mysql在查询过程中会查询多少条记录。如果是使用系统变量 max_join_size 来取得查询结果,这个乘积还可以用来确定会执行哪些多表select 语句。下面的例子展示了如何通过 explain提供的信息来较大程度地优化多表联合查询的性能。假设有下面的 select 语句,正打算用 explain 来检测:
从from子句可以看出select子句要进行多表查询,要从三个表tt, et 和do三个表中进行联合查询,看起来是四个表
重点看where比较子句:tt.submittime is null and tt.actualpc = et.employid and tt.assignedpc =et_1.employid and tt.clientid = do.custnmbr;
假设要比较的字段定义为表tt中的actualpc,actualpc 和clientid 均为 char(10)类型,et的employid 为char(15) 类型,do 的custnmbr为char(15) 类型,
这三个表的索引为tt有上那个索引:actualpc(值分布不均匀),assignedpc和clientid, et的为主键索引:employid (primary key),do表的也为主键索引custnmbr (primary key)
第一步,在任何优化措施未采取之前,经过 explain分析的结果显示如下:
在这里有个问题是当字段定义一样的时候,mysql就可以在这些字段上更快的是用索引(对isam类型的表来说,除非字段定义完全一样,否则不会使用索 引)。在这个前提下,varchar和 char是一样的除非它们定义的长度不一致。由于 tt.actualpc 定义为char(10),et.employid 定义为 char(15),二者长度不一致。
为了解决这个问题,需要用 alter table 来加大 actualpc的长度从10到15个字符:altertable tt modify actualpc varchar(15); 现在 tt.actualpc 和 et.employid 都是 varchar(15),在执行一次explain:
这还不够,它还可以做的更好:现在 rows值乘积已经少了74倍。这次查询需要用2秒钟。
第二个改变是消除在比较 tt.assignedpc = et_1.employid 和 tt.clientid= do.custnmbr 中字段的长度不一致问题:
altertable tt modify assignedpc varchar(15), ->modify clientid varchar(15);
这看起来已经是能做的最好的结果了。遗留下来的问题是,mysql默认地认为字段tt.actualpc的值是均匀分布的,然而表tt并非如此。幸好,我们可以很方便的让mysql分析索引的分布:mysql>analyze table tt; 到此为止,表连接已经优化的很完美了,explain 的结果如下:
请注意,explain 结果中的 rows字段的值也是mysql的连接优化程序大致猜测的,请检查这个值跟真实值是否基本一致。如果不是,可以通过在select 语句中使用 straight_join 来取得更好的性能,同时可以试着在from分句中用不同的次序列出各个表。
调整Mysql数据库性能:
Mysql 优化表命令
AnalyzeTable MySQL 的Optimizer(优化元件)在优化SQL语句时,首先需要收集一些相关信息,其中就包括表的cardinality(可以翻译为“散列程度”),它表示某个索引对应的列包含多少个不同的值——如果cardinality大大少于数据的实际散列程度,那么索引就基本失效了。
我们可以使用SHOW INDEX语句来查看索引的散列程度:SHOWINDEX FROM PLAYERS;
TABLE KEY_NAME COLUMN_NAMECARDINALITY
------- -------- ----------- -----------
PLAYERS PRIMARYPLAYERNO 14
因为此时PLAYER表中不同的PLAYERNO数量远远多于14,索引基本失效。
下面我们通过Analyze Table语句来修复索引:
ANALYZE TABLE PLAYERS;
SHOW INDEX FROM PLAYERS;
结果是:
TABLE KEY_NAME COLUMN_NAMECARDINALITY
------- -------- ----------- -----------
PLAYERS PRIMARYPLAYERNO 1000
此时索引已经修复,查询效率大大提高。
需要注意的是,如果开启了binlog,那么Analyze Table的结果也会写入binlog,我们可以在analyze和table之间添加关键字local取消写入。
Checksum Table数据在传输时,可能会发生变化,也有可能因为其它原因损坏,为了保证数据的一致,我们可以计算checksum(校验值)。使用MyISAM引擎的表会把checksum存储起来,称为live checksum,当数据发生变化时,checksum会相应变化。在执行Checksum Table时,可以在最后指定选项qiuck或是extended;quick表示返回存储的checksum值,而extended会重新计算checksum,如果没有指定选项,则默认使用extended。
Optimize Table经常更新数据的磁盘需要整理碎片,数据库也是这样,Optimize Table语句对MyISAM和InnoDB类型的表都有效。如果表经常更新,就应当定期运行OptimizeTable语句,保证效率。与Analyze Table一样,Optimize Table也可以使用local来取消写入binlog。对于经常修改的表,容易产生碎片,使在查询数据库时必须读取更多的磁盘块,降低查询性能。具有可变长的表都存在磁盘碎片问题,这个问题对blob数据类型更为突出,因为其尺寸变化非常大。可以通过使用optimize table来整理碎片,保证数据库性能不下降,优化那些受碎片影响的数据表。 optimize table可以用于MyISAM和BDB类型的数据表。实际上任何碎片整理方法都是用mysqldump来转存数据表,然后使用转存后的文件并重新建数据表;
Check Table数据库经常可能遇到错误,譬如数据写入磁盘时发生错误,或是索引没有同步更新,或是数据库未关闭MySQL就停止了。遇到这些情况,数据就可能发生错误:Incorrectkey file for table: ' '. Try to repair it. 此时,我们可以使用Check Table语句来检查表及其对应的索引。譬如我们运行CHECKTABLE PLAYERS; 结果是
TABLE OP MSG_TYPE MSG_TEXT
-------------- ----- -------- --------
TENNIS.PLAYERS check status OK
MySQL会保存表最近一次检查的时间,每次运行check table都会存储这些信息:
执行
SELECT TABLE_NAME, CHECK_TIME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'PLAYERS'
AND TABLE_SCHEMA ='TENNIS'; /*TENNIS是数据库名*/
结果是
TABLE_NAME CHECK_TIME
---------- -------------------
PLAYERS 2006-08-2116:44:25
Check Table还可以指定其它选项:
UPGRADE:用来测试在更早版本的MySQL中建立的表是否与当前版本兼容。
QUICK:速度最快的选项,在检查各列的数据时,不会检查链接(link)的正确与否,如果没有遇到什么问题,可以使用这个选项。
FAST:只检查表是否正常关闭,如果在系统掉电之后没有遇到严重问题,可以使用这个选项。
CHANGED:只检查上次检查时间之后更新的数据。
MEDIUM:默认的选项,会检查索引文件和数据文件之间的链接正确性。
EXTENDED:最慢的选项,会进行全面的检查。
Repair Table 用于修复表,只对MyISAM和ARCHIVE类型的表有效。
这条语句同样可以指定选项:
QUICK:最快的选项,只修复索引树。
EXTENDED:最慢的选项,需要逐行重建索引。
USE_FRM:只有当MYI文件丢失时才使用这个选项,全面重建整个索引。
与Analyze Table一样,Repair Table也可以使用local来取消写入binlog。