随手记——mysql

1,mysql: left, right, outer, inner, left outer, 以及 right outer.

2,导出数据:

mysql> SELECT * FROM tutorials_tbl 
    -> INTO OUTFILE '/tmp/tutorials.txt';
#导出csv格式
mysql> SELECT * FROM passwd INTO OUTFILE '/tmp/tutorials.txt'
    -> FIELDS TERMINATED BY ',' ENCLOSED BY '"'
    -> LINES TERMINATED BY '\r\n';

3,导入数据:mysqldump、load data和mysqlimport

#导出
$ mysqldump -u root -p TUTORIALS tutorials_tbl > dump.txt
#导入
$ mysql -u root -p database_name < dump.txt
#load data
mysql> LOAD DATA LOCAL INFILE 'dump.txt' INTO TABLE mytbl;
mysql> LOAD DATA LOCAL INFILE 'dump.txt' INTO TABLE mytbl
  -> FIELDS TERMINATED BY ':'
  -> LINES TERMINATED BY '\r\n';
mysql>LOAD DATA LOCAL INFILE 'dump.txt' 
    -> INTO TABLE mytbl (b, c, a);
$ mysqlimport -u root -p --local database_name dump.txt

4,将导出的数据直接导入到远程的服务器

$ mysqldump -u root -p database_name \
       | mysql -h other-host.com database_name

5,Explain 字段解析

EXPLAIN字段:
Table:显示这一行的数据是关于哪张表的
possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句
key:实际使用的索引。如果为NULL,则没有使用索引。MYSQL很少会选择优化不足的索引,
     此时可以在SELECT语句中使用USE INDEX(index)来强制使用一个索引
     或者用IGNORE INDEX(index)来强制忽略索引
key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好
ref:显示索引的哪一列被使用了,如果可能的话,是一个常数
rows:MySQL认为必须检索的用来返回请求数据的行数
type:这是最重要的字段之一,显示查询使用了何种类型。
     从最好到最差的连接类型为system、const、eq_reg、ref、range、index和ALL
system、const:可以将查询的变量转为常量.  如id=1; id为 主键或唯一键.
neq_ref:访问索引,返回某单一行的数据.(通常在联接时出现,查询使用的索引为主键或惟一键)
ref:访问索引,返回某个值的数据.(可以返回多行) 通常使用=时发生
range:这个连接类型使用索引返回一个范围中的行,比如使用>或<查找东西,
       并且该字段上建有索引时发生的情况(注:不一定好于index)
index:以索引的顺序进行全表扫描,优点是不用排序,缺点是还要全表扫描
ALL:全表扫描,应该尽量避免
Extra:关于MYSQL如何解析查询的额外信息,主要有以下几种
using index:只用到索引,可以避免访问表. 
using where:使用到where来过虑数据. 不是所有的where clause都要显示using where. 如以=方式访问索引.
using tmporary:用到临时表
using filesort:用到额外的排序. (当使用order by v1,而没用到索引时,就会使用额外的排序)
range checked for eache record(index map:N):没有好的索引.
6,索引及查询优化
索引的类型
普通索引:这是最基本的索引类型,没唯一性之类的限制。
唯一性索引:和普通索引基本相同,但所有的索引列值保持唯一性。
主键:主键是一种唯一索引,但必须指定为”PRIMARY KEY”。
全文索引:MYSQL从3.23.23开始支持全文索引和全文检索。在MYSQL中,全文索引的索引类型为FULLTEXT。
        全文索引可以在VARCHAR或者TEXT类型的列上创建。
大多数MySQL索引(PRIMARY KEY、UNIQUE、INDEX和FULLTEXT)使用B树中存储。
        空间列类型的索引使用R-树,MEMORY表支持hash索引。
单列索引和多列索引(复合索引)
索引可以是单列索引,也可以是多列索引。对相关的列使用索引是提高SELECT操作性能的最佳途径之一。
多列索引:
MySQL可以为多个列创建索引。一个索引可以包括15个列。对于某些列类型,可以索引列的左前缀,列的顺序非常重要。
多列索引可以视为包含通过连接索引列的值而创建的值的排序的数组。一般来说,即使是限制最严格的单列索引,它的限制能力也远远低于多列索引。
最左前缀
多列索引有一个特点,即最左前缀(Leftmost Prefixing)。假如有一个多列索引为key(firstname lastname age),当搜索条件是以下各种列的组合和顺序时,
MySQL将使用该多列索引:
firstname,lastname,age
firstname,lastname
firstname
也就是说,相当于还建立了key(firstname lastname)和key(firstname)。
索引主要用于下面的操作:
快速找出匹配一个WHERE子句的行。
删除行。当执行联接时,从其它表检索行。
对具体有索引的列key_col找出MAX()或MIN()值。由预处理器进行优化,检查是否对索引中在key_col之前发生所有关键字元素使用了WHERE key_part_# = constant。
在这种情况下,MySQL为每个MIN()或MAX()表达式执行一次关键字查找,并用常数替换它。如果所有表达式替换为常量,查询立即返回。例如:
SELECT MIN(key2), MAX (key2)  FROM tb WHERE key1=10;
如果对一个可用关键字的最左面的前缀进行了排序或分组(例如,ORDER BY key_part_1,key_part_2),排序或分组一个表。如果所有关键字元素后面有DESC,
关键字以倒序被读取。
在一些情况中,可以对一个查询进行优化以便不用查询数据行即可以检索值。如果查询只使用来自某个表的数字型并且构成某些关键字的最左面前缀的列,
为了更快,可以从索引树检索出值。
SELECT key_part3 FROM tb WHERE key_part1=1

合理的建立索引的建议:
(1)  越小的数据类型通常更好:越小的数据类型通常在磁盘、内存和CPU缓存中都需要更少的空间,处理起来更快。 
(2)  简单的数据类型更好:整型数据比起字符,处理开销更小,因为字符串的比较更复杂。在MySQL中,应该用内置的日期和时间数据类型,而不是用字符串来存储时间;
以及用整型数据类型存储IP地址。
(3)  尽量避免NULL:应该指定列为NOT NULL,除非你想存储NULL。在MySQL中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。
你应该用0、一个特殊的值或者一个空串代替空值
 
这部分是关于索引和写SQL语句时应当注意的一些琐碎建议和注意点。
1. 当结果集只有一行数据时使用LIMIT 1
2. 避免SELECT *,始终指定你需要的列
从表中读取越多的数据,查询会变得更慢。他增加了磁盘需要操作的时间,还是在数据库服务器与WEB服务器是独立分开的情况下。你将会经历非常漫长的网络延迟,
仅仅是因为数据不必要的在服务器之间传输。
3. 使用连接(JOIN)来代替子查询(Sub-Queries)
       连接(JOIN).. 之所以更有效率一些,是因为MySQL不需要在内存中创建临时表来完成这个逻辑上的需要两个步骤的查询工作。
4. 使用ENUM、CHAR 而不是VARCHAR,使用合理的字段属性长度
5. 尽可能的使用NOT NULL
6. 固定长度的表会更快
7. 拆分大的DELETE 或INSERT 语句
8. 查询的列越小越快
 
 Where条件
在查询中,WHERE条件也是一个比较重要的因素,尽量少并且是合理的where条件是很重要的,尽量在多个条件的时候,把会提取尽量少数据量的条件放在前面,
减少后一个where条件的查询时间。
有些where条件会导致索引无效:
where子句的查询条件里有!=,MySQL将无法使用索引。
where子句使用了Mysql函数的时候,索引将无效,比如:select * from tb where left(name, 4) = ‘xxx’
使用LIKE进行搜索匹配的时候,这样索引是有效的:select * from tbl1 where name like ‘xxx%’,而like ‘%xxx%’ 时索引无效


7,权限管理与用户管理

#GRANT 语法:
GRANT privileges (columns)
    ON (what)
    TO (user) IDENTIFIED BY "(password)"
    WITH GRANT OPTION 
* columns  权限[ALTER,CREATE,DELETE,DROP,INDEX,INSERT,REFERENCE,SELECT,UPDATE,FILE,PROCESS,RELOAD,SHUTDOWN,ALL,USAGE]
* what 权限运用的级别 db_name.table_name,*.*等
* user 权限授予的用户  user@服务器   user@*,[email protected]
* password 口令【可选】
示例:
GRANT ALL ON samp_db.* TO boris@localhost IDENTIFIED BY "ruby"
GRANT ALL ON samp_db.* TO [email protected] IDENTIFIED BY "quartz"
GRANT ALL ON samp_db.* TO max@% IDENTIFIED BY "diamond"
GRANT ALL ON samp_db.* TO [email protected] IDENTIFIED BY "quartz";
GRANT ALL ON samp_db.* TO [email protected] IDENTIFIED BY "ruby"
GRANT ALL ON samp_db.* TO [email protected].% IDENTIFIED BY "quartz"
GRANT ALL ON samp_db.* TO [email protected]/17 IDENTIFIED BY "ruby"

GRANT ALL ON samp_db.president TO "my friend"@"boa.snake.net" 
GRANT ALL ON *.* TO ethel@localhost IDENTIFIED BY "coffee" WITH GRANT OPTION

GRANT RELOAD ON *.* TO flushl@localhost IDENTIFIED BY "flushpass" 

GRANT ALL ON samp_db TO [email protected] INDETIFIED BY "rock"
GRANT SELECT ON samp_db TO ro_user@% INDETIFIED BY "rock"

GRANT SELECT,INSERT,DELETE,UPDATE ON samp_db TO [email protected] INDETIFIED BY "rock"

GRANT SELECT ON samp_db.member TO bill@localhost INDETIFIED BY "rock"
GRANT UPDATE (expiration) ON samp_db. member TO bill@localhost //修改特定列
GRANT UPDATE (street,city,state,zip) ON samp_db TO assistant@localhost

//管理权限 WITH GRANT OPTION
GRANT ALL ON sales.* TO alicia@%.big.corp.com INDETIFIED BY "applejuice" WITH GRANT OPTION

//撤权
REVOKE privileges (columns) ON what FROM user//已登录连接的用户仍有权限

//删除用户
%mysql -u root mysql
mysql>DELETE FROM user
     ->WHERE User="user_name" and Host="host_name";
mysql>FLUSH PRIVILEGES; 

授权表。(当你使用GRANT和REVOKE语句时,表自动重载,而你直接修改授权表时不是

//查看用户权限
//查看 MySQL 用户权限
show grants;
show grants for dba1@localhost;
//刷新权限
mysql>FLUSH PRIVILEGES; 

//修改密码
INSERT INTO mysql.user (Host,User,Password) VALUES('%','jeffrey',PASSWORD('biscuit')); 
REPLACE INTO mysql.user (Host,User,Password) VALUES('%','jeffrey',PASSWORD('biscuit')); 
update mysql.user set password=PASSWORD('111111') where user='root';
-- FLUSH PRIVILEGES; 

8,时间函数

1. 选取日期时间的各个部分:日期、时间、年、季度、月、日、小时、分钟、秒、微秒
set @dt = '2008-09-10 07:15:30.123456';
select date(@dt);        -- 2008-09-10
select time(@dt);        -- 07:15:30.123456
select year(@dt);        -- 2008
select quarter(@dt);     -- 3
select month(@dt);       -- 9
select week(@dt);        -- 36
select day(@dt);         -- 10
select hour(@dt);        -- 7
select minute(@dt);      -- 15
select second(@dt);      -- 30
select microsecond(@dt); -- 123456
2>时间计算
mysql> SELECT DATE('2003-12-31 01:02:03');  -> '2003-12-31'
mysql> SELECT DATEDIFF('1997-12-31 23:59:59','1997-12-30');  -> 1
mysql> SELECT DATEDIFF('1997-11-30 23:59:59','1997-12-31');  -> -31

DATE_ADD(date,INTERVAL expr type) 
DATE_SUB(date,INTERVAL expr type) 
type 值	预期的		 expr 格式
MICROSECOND		MICROSECONDS
SECOND			SECONDS
MINUTE			MINUTES
HOUR			HOURS
DAY			DAYS
WEEK			WEEKS
MONTH			MONTHS
QUARTER			QUARTERS
YEAR			YEARS
SECOND_MICROSECOND	'SECONDS.MICROSECONDS'
MINUTE_MICROSECOND	'MINUTES.MICROSECONDS'
MINUTE_SECOND		'MINUTES:SECONDS'
HOUR_MICROSECOND	'HOURS.MICROSECONDS'
HOUR_SECOND		'HOURS:MINUTES:SECONDS'
HOUR_MINUTE		'HOURS:MINUTES'
DAY_MICROSECOND		'DAYS.MICROSECONDS'
DAY_SECOND		'DAYS HOURS:MINUTES:SECONDS'
DAY_MINUTE		'DAYS HOURS:MINUTES'
DAY_HOUR		'DAYS HOURS'
YEAR_MONTH		'YEARS-MONTHS'

mysql> SELECT INTERVAL 1 DAY + '1997-12-31';  -> '1998-01-01'
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_SUB('1998-01-01 00:00:00',INTERVAL '1 1:1:1' DAY_SECOND);->'1997-12-30 22:58:59'
        
DATE_FORMAT(date,format) 
根据format 字符串安排date 值的格式。

说明符	说明
%a	工作日的缩写名称  (Sun..Sat)
%b	月份的缩写名称  (Jan..Dec)
%c	月份,数字形式(0..12)
%D	带有英语后缀的该月日期  (0th, 1st, 2nd, 3rd, ...)
%d	该月日期, 数字形式 (00..31)
%e	该月日期, 数字形式(0..31)
%f	微秒 (000000..999999)
%H	小时(00..23)
%h	小时(01..12)
%I	小时 (01..12)
%i	分钟, 数字形式 (00..59)
%j	一年中的天数 (001..366)
%k	小时 (0..23)
%l	小时 (1..12)
%M	月份名称 (January..December)
%m	月份, 数字形式 (00..12)
%p	上午(AM)或下午( PM)
%r	时间 , 12小时制 (小时hh:分钟mm:秒数ss 后加 AM或PM)
%S	秒 (00..59)
%s	秒 (00..59)
%T	时间 , 24小时制 (小时hh:分钟mm:秒数ss)
%U	周 (00..53), 其中周日为每周的第一天
%u	周 (00..53), 其中周一为每周的第一天 
%V	周 (01..53), 其中周日为每周的第一天 ; 和 %X同时使用
%v	周 (01..53), 其中周一为每周的第一天 ; 和 %x同时使用
%W	工作日名称 (周日..周六)
%w	一周中的每日 (0=周日..6=周六)
%X	该周的年份,其中周日为每周的第一天, 数字形式,4位数;和%V同时使用
%x	该周的年份,其中周一为每周的第一天, 数字形式,4位数;和%v同时使用
%Y	年份, 数字形式,4位数
%y	年份, 数字形式 (2位数)
%%	‘%’文字字符

GET_FORMAT(DATE|TIME|DATETIME, 'EUR'|'USA'|'JIS'|'ISO'|'INTERNAL') 
函数调用		结果  
GET_FORMAT(DATE,'ISO')	'%Y-%m-%d'  
GET_FORMAT(TIME,'ISO')	'%H:%i:%s' 

mysql> SELECT DATE_FORMAT('2003-10-03',GET_FORMAT(DATE,'EUR'));  -> '03.10.2003'
        
LAST_DAY(date) 
获取一个日期或日期时间值,返回该月最后一天对应的值。若参数无效,则返回NULL。
mysql> SELECT LAST_DAY('2003-02-05');  -> '2003-02-28'
mysql> SELECT LAST_DAY('2003-03-32');   -- NULL
 
SELECT TIMESTAMPDIFF(hour,'2003-02-01 00:12:00','2003-05-01 23;50:00')  
  ->2159
  
mysql> select  CURDATE(),CURTIME(),UTC_DATE(),UTC_TIME(),UTC_TIMESTAMP(),CURRENT_TIMESTAMP(),CURRENT_TIME(),CURRENT_DATE();
+------------+-----------+------------+------------+---------------------+---------------------+----------------+----------------+
| CURDATE()  | CURTIME() | UTC_DATE() | UTC_TIME() | UTC_TIMESTAMP()     | CURRENT_TIMESTAMP() | CURRENT_TIME() | CURRENT_DATE() |
+------------+-----------+------------+------------+---------------------+---------------------+----------------+----------------+
| 2014-09-15 | 20:28:57  | 2014-09-15 | 12:28:57   | 2014-09-15 12:28:57 | 2014-09-15 20:28:57 | 20:28:57       | 2014-09-15     |
+------------+-----------+------------+------------+---------------------+---------------------+----------------+----------------+
1 row in set (0.00 sec)

MySQL 拼凑日期、时间函数:makdedate(year,dayofyear), maketime(hour,minute,second)
select makedate(2001,31);   -- '2001-01-31'
select makedate(2001,32);   -- '2001-02-01'
select maketime(12,15,30);  -- '12:15:30'

MySQL (Unix 时间戳、日期)转换函数:
elect unix_timestamp();                       -- 1218290027
select unix_timestamp('2008-08-08');          -- 1218124800
select unix_timestamp('2008-08-08 12:30:00'); -- 1218169800

select from_unixtime(1218290027);             -- '2008-08-09 21:53:47'

MySQL 时区(timezone)转换函数
convert_tz(dt,from_tz,to_tz)
select convert_tz('2008-08-08 12:00:00', '+08:00', '+00:00'); -- 2008-08-08 04:00:00






你可能感兴趣的:(随手记——mysql)