mysql基础知识(mysql新手教程)(使用方法简单教程)
本篇文章主要介紹MySQL基礎(chǔ)知識,數(shù)據(jù)庫它是一個以某種有組織的方式存儲的數(shù)據(jù)集合,保存有組織的數(shù)據(jù)的容器(通常是一個文件或一組文件),感興趣的朋友可以移步風(fēng)君子博客mysql視頻教程頻道了解一下。Mysql 數(shù)據(jù)庫必須在Mysql服務(wù)下啟動。
在windows 下 啟動Mysql cd到mysql\bin 目錄下 在dos窗口下 啟動\關(guān)閉mysql服務(wù)
//啟動mysql服務(wù) mysqld --console //關(guān)閉mysql服務(wù) mysqladmin -uroot shutdown
登錄后復(fù)制
SQL分類
SQL 主要語句可以劃分為一下3類
-
DDL:數(shù)據(jù)定義語言,這些語句定義不同的數(shù)據(jù)段、數(shù)據(jù)庫、表、列、索引等數(shù)據(jù)庫對象。常用語句關(guān)鍵字主要包括create,drop,alter等
-
DML:數(shù)據(jù)操作語句,用于添加、刪除、更新和查詢數(shù)據(jù)庫記錄,并檢查數(shù)據(jù)完整性。常用語句關(guān)鍵字主要包括 insert,delete,update和select等。
-
DCL數(shù)據(jù)控制語句,用于控制不同數(shù)據(jù)段直接的許可和訪問級別的語句。這些語句定義了數(shù)據(jù)庫、表、字段、用戶的訪問權(quán)限和安全級別。主要 的語句包括關(guān)鍵字grant、revoke等
DDL語句
是對數(shù)據(jù)庫內(nèi)部的對象進(jìn)行創(chuàng)建 、刪除、修改等操作語言,它和DML語句最大的區(qū)別是DML只是對表內(nèi)部數(shù)據(jù)操作,而不涉及表的定義、結(jié)構(gòu)的修改,更不會涉及其他對象。DDL更多地由數(shù)據(jù)庫管理員(DBA)使用。
連接mysql服務(wù)器 mysql -uroot -p 創(chuàng)建數(shù)據(jù)庫test1 create database test1; 顯示有哪些數(shù)據(jù)庫 show databases; //mysql 自動創(chuàng)建的表有 information_schema:主要存儲了系統(tǒng)中的一些數(shù)據(jù)庫信息,比如用戶表信息、列信息、權(quán)限信息、字符集信息、分區(qū)信息等等 cluster:存儲了系統(tǒng)的集群信息 mysql:存儲了系統(tǒng)的用戶權(quán)限信息。 test:系統(tǒng)自動創(chuàng)建的測試數(shù)據(jù)庫,任何用戶都可以訪問 選擇數(shù)據(jù)庫 use test1 顯示test1數(shù)據(jù)庫中創(chuàng)建的所有表 show tables 刪除數(shù)據(jù)庫 drop database test1; 創(chuàng)建表 create table emp(ename varchar(10),hiredata date,sal decimal(10,2),deptno int(2)); 查看表定義 desc emp; 查看創(chuàng)建表的定義 show create table emp; 刪除表 drop table emp; 修改表 alter table emp modify ename varchar(20); 增加表字段 alter table emp add column age int(3); 刪除表字段 alter table emp drop column age; 字段改名 alter table emp change age age1 int(4); change 和modify都可以修改表的定義,不同的是change后面需要寫兩次列名,不方便,但是change的優(yōu)點是可以修改列名稱,則modify則不能 修改字段排序 alter table emp add birth date after ename; alter table emp modify age int(3) first; 更改表名 alter table emp rename emp1;
登錄后復(fù)制
DML語句
是指對數(shù)據(jù)庫中表記錄的操作,主要包括表記錄的插入(insert)、更新(update)、刪除(delete)和查詢(select)。
插入記錄
insert into emp(ename,hiredate,sal,deptno)values('zzx1','2000-01-01','2000',1);
也可以不用指定字段名稱,但是values后面的順序要和字段的排列順序一致
inset into emp('zzx1','2000-01-01','2000',1);
含可空字段、非空但是含有默認(rèn)值的字段、自增字段、可以不用再insert后的字段列表里面出現(xiàn),values后面只寫對應(yīng)字段名稱的value,沒寫的字段可以自動設(shè)置為null、默認(rèn)值、自增的下一個數(shù)字
批量增加用逗號隔開
insert into dept values(5,'xxx'),(8,'xxx');
更新記錄
update emp set sal=4000 where ename='xxx';
刪除記錄
delete from emp where ename='doney';
查詢記錄
select * from emp;
*表示所有記錄,也可以用逗號隔開的字段來選擇查詢
查詢不重復(fù)的記錄
select distinct deptno from emp;
條件查詢
用where關(guān)鍵字來實現(xiàn),可以使用<>!=等多條件可以使用or、and等
排序和限制
desc和asc是排序關(guān)鍵字,desc是降序、asc是升序排列 ORDER BY 排序,默認(rèn)是升序
select * from emp order by sal;
如果排序字段的值一樣,則值相同的字段按照第二個排序字段進(jìn)行排序,如果只有一個排序字段,則相同字段將會無序排序
select * from emp order by deptno,sal desc;
限制
select * from emp order by sal limit 3;
//前者是起始偏移量,后者是顯示行數(shù)
select * from emp order by sal limit 1,3;
limit 和order by 一起使用來做分頁
聚合
用戶做一下些匯總操作
sum(求和),count(*)(記錄數(shù)),max(最大值),min(最小值)
with rollup 是可選語法,表示是否對分類聚合后的結(jié)果進(jìn)行再匯總
having 表示對分類后的結(jié)果在進(jìn)行條件的過濾。
select deptno,count(1) from emp group by deptno having count(1)>=1;
登錄后復(fù)制
表連接
大類上分為外連接和內(nèi)連接
外鏈接 又分為左連接和右連接
左連接:包含所以的左邊表中的記錄甚至是右邊表中沒有和它匹配的記錄。
右連接:同上
select ename,detname from emp left join dept on emp.deptno=dept.deptno; 左連接和右連接可以相互轉(zhuǎn)換
登錄后復(fù)制
子查詢
select * from emp where deptno in(select deptno from dept); 如果子查詢記錄唯一,可以使用=替代in select * from emp where deptno =(select deptno from dept limit 1);
登錄后復(fù)制
記錄查詢
將兩個表的數(shù)據(jù)按照一定的查詢出來后,將結(jié)果合在一起顯示
union all 是將結(jié)果集合并在一起,而union是將union all后的結(jié)果在進(jìn)行一次distinct,去除重復(fù)
select deptno from emp union all select deptno from dept; select demtno from emp union select deptno from dept;
登錄后復(fù)制
? xxx 來查看
如果要查看類別 ? data types 具體的 ? int 查看語法 如 ? create table
登錄后復(fù)制
數(shù)據(jù)類型
對于整形數(shù)據(jù),MySql還支持在類型名稱后面的小括號設(shè)置寬度,默認(rèn)設(shè)置為int(11),配合zerofill, 當(dāng)數(shù)字位數(shù)不夠的時候,用字符‘0’填充 alter table t1 modify id1 int zerofill
登錄后復(fù)制
對于小數(shù),MySql 分為兩種,浮點數(shù)和定點數(shù)。浮點數(shù)包括float和double,而定點數(shù)只有decimal,定點數(shù)在Mysql內(nèi)部是以字符串形式存放,比浮點數(shù)更精確,適合用于貨幣等精度高的數(shù)據(jù)
浮點數(shù)和定點數(shù)可以用類型名稱加(M,D) M是幾位,D是位于小數(shù)點后面幾位。
日期類型
-
DATE來表示年月日
-
DATETIME來表示年月日時分秒
-
TIME來表示時分秒
-
當(dāng)前系統(tǒng)時間,通常用TIMESTAMP來表示
TIMESTAMP
創(chuàng)建一個字段為TIMESTAMP類型,系統(tǒng)自動創(chuàng)建了默認(rèn)值為CURRENT_TIMESTAMP(系統(tǒng)日期)。同時MySql規(guī)定TIMESTAMP類型字段一列只能有一個默認(rèn)值current_timestamp。如果修改會報錯.
TIMESTAMP 另一個重要特點是與時區(qū)有關(guān)。當(dāng)插入時間時,先轉(zhuǎn)換為本地時區(qū)后存放,而從數(shù)據(jù)庫取出時,同樣會將日期轉(zhuǎn)換為本地時區(qū)后顯示,這樣兩個時區(qū)的用戶看到同一個時區(qū)可能就不一樣
查看當(dāng)前時區(qū) show variables like 'time_zone'; 修改時區(qū) set time_zone='+9.00';
登錄后復(fù)制
DATETIME插入的格式
YYYY-MM-DD HH:MM:SS 或YY-MM-DD HH:MM:SS 的字符串允許任何標(biāo)點符號用來做時間部分的間隔符 如92@12@31 11^30^45 YYYYMMDDHHMMSS 或YYMMDDHHMMSS的格式?jīng)]有間隔符的字符串
登錄后復(fù)制
字符串類型
CHAR和VARCHAR類型
兩者的主要區(qū)別是存儲方式不同:CHAR列的長度固定為創(chuàng)建表時聲明的長度,長度可以為0-255;二VARCHAR列中的值是可變長度。同時在檢索的時候,CHAR列刪除尾部的空格 ,而VARCHAR保留空格,由于CHAR是固定長度,所以它的處理速度別VARCHAR快很多,但是其缺點是浪費內(nèi)存,在使用中VARCHAR被更多的使用
create table vc (v varchar(4),c char(4))
insert into vc values('ab ','ab ');
selelct length(v),length(c) from vc
//4,2
登錄后復(fù)制登錄后復(fù)制
枚舉
create table vc (v varchar(4),c char(4))
insert into vc values('ab ','ab ');
selelct length(v),length(c) from vc
//4,2
登錄后復(fù)制登錄后復(fù)制
set類型
set類型可以一次選取多個成員
create table t2 (col set('a','b','c','d'));
INSERT into t2 VALUE ('a,b'),('a,d,a'),('a,b'),('a,c'),('a');
對于(a,d,a)這個包含重復(fù)成員的集合只取一次 結(jié)果為’a,d'
登錄后復(fù)制
運算符
p==/==除法獲取商 MOD==%==除法獲取余數(shù)
登錄后復(fù)制
=和<=>區(qū)別
不能用于null比較,后者可以
between 使用格式 a between min and max 等價于 a>=min and a<=max in的使用格式 a in(value1,value2...); like 使用格式如 a like %123%,當(dāng)字符串含有123則返回1 否則返回0 REGEXP 使用格式 str REGEXP str_pat 當(dāng)str字符串中含有str_pat 相匹配的字符串,則返回1
登錄后復(fù)制
位運算
| 運算符 | 作用 |
|---|---|
| & | and |
| | | or |
| ^ | xor |
| ~ | 位異或 |
| > | 位右移 |
| << | 位左移 |
常用函數(shù)
字符串函數(shù)
| 函數(shù) | 功能 |
|---|---|
| CONCAT(s1,s2,s3…) | 連接s1到sn的字符串(任何字符串和null拼接都是null) |
| insert(str,x,y,instr) | 將字符串str從x位置開始,y字符長的子串替換為字符串instr |
| lower(str) | 將字符串str中所有字符變?yōu)樾?/td> |
| UPPER(str) | 大寫 |
| LEFT(str,x) | 返回字符串str最左邊x個字符 |
| RIGHT(str,x) | 返回字符串str最右邊的x個字符 |
| LPAD(str,n,pad) | 用字符串pad對str最左邊進(jìn)行填充,直到長度為n個字符串長度 |
| PRPAD(str,n,pad) | 用字符串pad對str最右邊進(jìn)行填充,直到長度為n個字符串長度 |
| LTRIM(str) | 去掉字符串str左側(cè)的空格 |
| RIGHT(str) | 去掉字符串str行尾的空格 |
| REPEAT(str,x) | 返回str重復(fù)x次的結(jié)果 |
| REPLACE(Str,a,b) | 用字符串b替換字符串str中所有出現(xiàn)的字符串a(chǎn) |
| STRCMP(s1,s2) | 比較字符串s1和s2 |
| TRIM(str) | 去掉行尾和行頭的空格 |
| SUBSTRING(str,x,y) | 返回字符串str x位置起y字符串長度的字串 |
數(shù)字函數(shù)
| 函數(shù) | 功能 |
|---|---|
| ABS(X) | 返回x的絕對值 |
| CEIL(X) | 返回大于x的最小整數(shù)值 |
| FLOOR(X) | 返回小于x的最大整數(shù)值 |
| MOD(x,y) | 返回x/y的模 |
| RAND() | 返回0-1內(nèi)的隨機值 |
| ROUND(x,y) | 返回參數(shù)x的四舍五入的有y位小數(shù)的值 |
| TRUNCATE(x,y) | 返回數(shù)值x截斷為y位小樹的結(jié)果 |
日期和時間函數(shù)
| 函數(shù) | 功能 |
|---|---|
| CURDATE() | 返回當(dāng)前日期 |
| CURTIME() | 返回當(dāng)前時間 |
| NOW() | 返回當(dāng)前的日期和時間 |
| UNIX_TIMESTAMP(date) | 返回date的unix時間戳 |
| FROM_UNIXTIME | 返回UNIX時間戳的日期值 |
| WEEK(date) | 返回日期date為一年中的第幾周 |
| YEAR(date) | 返回日期date的年份 |
| HOUR(time) | 返回time的小時值 |
| MINUTE(time) | 返回time的分鐘值 |
| MONTHNAME(date) | 返回date的月份名 |
| DATE_FROMATE(date,fmt) | 返回按字符串fmt格式化日期date值 |
| DATE_ADD(date,interval expr type) | 返回一個日期或時間值加上一個時間間隔的時間值 |
| DATEDIFF(expr,expr2) | 返回起始時間expr和結(jié)束時間expr2之間的天數(shù) |
流程函數(shù)
| 函數(shù) | 功能 |
|---|---|
| IF(value,t f) | 如果value是真 返回 t;否則返回f |
| IFNULL(value1,value2) | 如果value1不為空,返回value1,負(fù)責(zé)返回value2 |
| CASE WHEN[value1] THEN[value2]…ELSE[default] END | 如果value1是真,返回result1否則返回defalut |
| case [expr] WHEN[value1] THEN[value2]…ELSE[default] END | 如果expr等于value1,返回result1否則返回defalut |
實例
create table salary(userid int ,salary decimal(9,2)); insert into salary values(1,1000),(2,2000),(3,3000),(4,4000),(5,5000),(1,null); select * from salary select if(salary>2000,'high','low') from salary; select ifnull(salary,0) from salary; select case when salary <=2000 then 'low' else 'high' end from salary; select case salary when 1000 then 'low' when 2000 then 'mid' else 'high' end from salary;
登錄后復(fù)制登錄后復(fù)制
其他函數(shù)
| 函數(shù) | 功能 |
|---|---|
| DATABASE() | 返回的確數(shù)據(jù)庫庫名 |
| VERSION() | 返回當(dāng)前數(shù)據(jù)庫版本 |
| USER() | 返回當(dāng)前登錄用戶名 |
| INET_ATON(IP) | 返回ip地址的數(shù)字表示 |
| INET_NTOA(num) | 返回數(shù)字代表的ip地址 |
| PASSWORD(str) | 返回字符串str加密版本 |
| MD5() | 返回字符串的md5值 |
MySql引擎
MySql支持的存儲引擎包括MyISAM、InnoDB、BDB、MEMORY、MERGE、EXAMPLE、NDB Cluster、ARCHIVE、CSV、BLACKHOLE、FEDERATED等,其中InnoDB和BDB提供事務(wù)安全表,用戶可以選擇不同的數(shù)據(jù)存儲引擎來提高應(yīng)用的效率
創(chuàng)建表如果不指定存儲引擎,系統(tǒng)默認(rèn)使用默認(rèn)存儲引擎,MySql5.5之前的默認(rèn)引擎是MyISAM,5.5之后改為InnoDB。如果要修改默認(rèn)的存儲引擎,可以在參數(shù)文件中設(shè)置default-table-type.
create table salary(userid int ,salary decimal(9,2)); insert into salary values(1,1000),(2,2000),(3,3000),(4,4000),(5,5000),(1,null); select * from salary select if(salary>2000,'high','low') from salary; select ifnull(salary,0) from salary; select case when salary <=2000 then 'low' else 'high' end from salary; select case salary when 1000 then 'low' when 2000 then 'mid' else 'high' end from salary;
登錄后復(fù)制登錄后復(fù)制
MyISAM
MyISAM 不支持事務(wù)、也不 不支持外鍵,其優(yōu)點是速度快,對事務(wù)完整性沒有要求。以SELECT和INSERT為主的應(yīng)用基本上都就可以使用這個表
InnoDB
InnoDB存儲引擎提供了具有提交、回滾和崩潰恢復(fù)能力的事務(wù)安全。但是對比MyISAM的存儲引擎,InnoDB寫的處理效率差一些,并且會占用更多的磁盤空間以保留數(shù)據(jù)和索引。
create table autoincre_demo (i smallint not null auto_increment,name varchar(10),primary key(i))engine=innodb;insert into autoincre_demo values(1,'1'),(0,'2'),(null,'3')
登錄后復(fù)制
如果插入空或者0,則實際插入的將是自動增長后的值。
可以通過以下語句強制設(shè)置自動增加列的初始值,默認(rèn)從1開始,但是該強制的默認(rèn)值是保留到內(nèi)存中,如果數(shù)據(jù)庫從起,這個強制的默認(rèn)值會丟失,就需要數(shù)據(jù)庫啟動后重新設(shè)置
ALTER TABLE *** auto_increment =n
登錄后復(fù)制
MEMORY
memory 存儲引擎使用存在于內(nèi)存中的內(nèi)容來創(chuàng)建表,每個MEMORY表實際對應(yīng)一個磁盤文件,格式是.fm,MEMORY表的訪問非常快,因為它的數(shù)據(jù)是放在內(nèi)存中,并且默認(rèn)使用HASH索引,但是一旦服務(wù)關(guān)閉,表中的數(shù)據(jù)就會
alter table t2 engine=memory; show TABLE status like 't2' 給memory表創(chuàng)建索引。可以指定hash索引還是btree索引 create index mem_hash using hash on tab_memory(city_id);
登錄后復(fù)制
在啟動MySql服務(wù)的時候使用–init-file選項,把INSERT INTO … SELECT或LOAD DATA INFILE這樣的語句放入這個文件中,就可以在服務(wù)啟動時從持久穩(wěn)固的數(shù)據(jù)源裝載表
服務(wù)器需要足夠的內(nèi)存來維持同一時間使用的MEMORY表,當(dāng)不需要MEMORY表的內(nèi)容,要釋放MEMORY表的內(nèi)存,執(zhí)行DELETE FROM或 TRUNCATE TABLE 或者是DROP TABLE
每個MEMORY表中可以放置的數(shù)據(jù)量的大小,受max_heap_table_size系統(tǒng)變量的約束,初始值是16mb,可以根據(jù)需要加大、
MEMORY類型的存儲引擎主要用在那些內(nèi)容變化不平凡的表,或作為統(tǒng)計操作的中間結(jié)果表,便于高效的對中間結(jié)果進(jìn)行分析并得到最終的統(tǒng)計結(jié)果。
TokuDB
TokuDB是第三方的存儲引擎,是一個高性能、支持事務(wù)處理的MySql和MariaDB的存儲引擎,具有高擴展性、高壓縮、高效率的寫入性能,支持大多數(shù)在線的DDL操作
TokuDB 特別適用的場景
-
日志數(shù)據(jù),因為日志數(shù)據(jù)通常插入頻繁且儲存量大
-
歷史數(shù)據(jù),通常不會有在寫的操作,可以利用TokuDB的高壓縮特性進(jìn)行存儲
-
在線DDL頻繁的場景
幾種常用存儲引擎的適用環(huán)境
-
MyISAM:如果應(yīng)用是以讀操作和插入操作為主,只有很少的更新和刪除操作,并且對事務(wù)的完整性,并發(fā)性要求不高,那么選擇這個引擎非常合適
-
Innodb:用于事務(wù)的處理,支持外鍵。如果應(yīng)用對事務(wù)的完整性較高的要求,在并發(fā)條件下要求數(shù)據(jù)的一致性,數(shù)據(jù)除了插入和查詢外,還包括很多的更新和刪除操作,那么Innodb存儲引擎比較適合
-
MEMORY:將所有數(shù)據(jù)都存在RAM中,如果需要快速定位記錄和其他類似數(shù)據(jù)的環(huán)境下,可以提供極快的訪問,缺陷在于對表大小的限制,太大的表無法緩存在內(nèi)存中,其次是要確保表的數(shù)據(jù)是可恢復(fù)的.
-
MERGE:用于將一系列等同MyISAM表以邏輯方式組合在一起,并作為一個對象引用它們。MERGE表的優(yōu)點在于可以突破單個MyISAM表大小的限制,并且通過將不同的表分布在多個磁盤上,可以有效的改善MERGE表的訪問效率
Text與BLOB
如果保存少量字符串會選擇CHAR和VARCHAR 但是保存較大文本時,選擇text或blob,兩者主要差別是blob能用來保存二進(jìn)制數(shù)據(jù)如圖片;而text只能保存字符數(shù)據(jù)
BLOB與TEXT引起的性能問題,特別是在執(zhí)行大量的刪除數(shù)據(jù)時,刪除操作會留下很大的空洞,以后填入這些空洞的記錄在插入的性能上會有影響,建立定期使用OPTIMIZE TABLE對這類表進(jìn)行碎屏整理
optimize table t
登錄后復(fù)制
使用合成的索引來提供大文本字段的查詢性能
合成索引就是根據(jù)大文本字段的內(nèi)容建立一個散列值,并把值存儲在單獨的數(shù)據(jù)列中,接下來就是通過檢索散列值找到數(shù)據(jù)行,但是只能做到精確匹配不能使用范圍搜索。可以使用MD5,SHA1,CRC32 等生成散列值,使用精確匹配,在一定程度上減少了I/O,提高了查詢效率。如果散列算法生成的字符串帶有尾部空格,就不要存儲在CHAR或VARCHAR列中,它會受尾部空格的影響
如果需要對BLOB或CLOB字段進(jìn)行模糊查詢,MySQL提高前綴索引,也就是只為字段的前n列創(chuàng)建索引 desc select * from t where context like 'beijing%' \G;
登錄后復(fù)制
注意事項
-
在不必要的時候避免檢索大型的BLOB或TEXT:如SELECT * 查詢,盡量從符合條件的數(shù)據(jù)行中檢索BLOB或TEXT指
-
把BLOB或TEXT列分離到單獨表中:在某些環(huán)境下,如果把這些數(shù)據(jù)列移動到第二張數(shù)據(jù)表中,可以把原數(shù)據(jù)表中的數(shù)據(jù)列轉(zhuǎn)換為固定長度的數(shù)據(jù)行格式,減少主表的碎片,可以得到固定長度數(shù)據(jù)行的性能優(yōu)勢。還可以在運行SELECT * 查詢的時候不會通過網(wǎng)絡(luò)傳輸大量的BLOB或TEXT指
設(shè)計索引的原則
-
搜索的索引列,不一定是所要選擇的列。最適合索引的列是出現(xiàn)在where字句中的列,或連接字句中指定的列,而不是出現(xiàn)在select關(guān)鍵字后的列表中的列
-
使用唯一索引.考慮到某列中的值分布,索引的列基礎(chǔ)越大,索引的效果越好。入存放出生日期的列具有各部相同的值,很容易區(qū)分,但是記錄性別的列,只含有男和女對此類進(jìn)行索引沒有多大好處
-
使用短檢索。如果對字符串進(jìn)行檢索,應(yīng)該指定一個前綴長度。例如:一個CHAR(200)列,如果前10個或20個字符內(nèi),多數(shù)值是唯一的,那么就不要對整個列進(jìn)行檢索。對前10個或20個字符進(jìn)行檢索能夠節(jié)省大量索引空間,是查詢更快。
-
利用最左前綴。在創(chuàng)建一個n列索引時,實際是創(chuàng)建了MySQL可利用的n個索引。多列索引可起幾個索引的作用,因為可利用索引最左邊的列級來匹配。
-
不要過度索引。每個索引都是占用額外的磁盤空間,并降低寫操作的性能。在修改表內(nèi)容的時候,索引必須進(jìn)行相應(yīng)的更新,有時候需要重構(gòu)。如果有一個索引很少被用到,那么會不必要的減緩表的修改速度。此外,mysql在生成一個執(zhí)行計劃時,要考慮各個索引,這也要花費時間。創(chuàng)建多余的索引給查詢優(yōu)化帶來了更多的工作
-
對于Innodb,記錄默認(rèn)會按照一定的順序排序,如果有明確的定義主鍵,則按照主鍵排序順序保存。
存儲過程和函數(shù)
什么是存儲過程和函數(shù)
存儲過程和函數(shù)是事先經(jīng)過編譯并存儲在數(shù)據(jù)庫中的一段SQL語句的集合,調(diào)用存儲過程和函數(shù)
可以簡化應(yīng)用開發(fā)人員的很多工作,減少數(shù)據(jù)在數(shù)據(jù)庫和應(yīng)用服務(wù)器之間的傳輸,對于提供數(shù)據(jù)處理的效率是有好處的。
存儲過程很函數(shù)的區(qū)別在于函數(shù)必須有返回值,而存儲過程沒有,儲存過程的參數(shù)可以使用IN,OUT,INOUT類型,而函數(shù)的參數(shù)只能是IN類型的。如果有函數(shù)從其他類型的數(shù)據(jù)庫遷移到MySQL,那么就可能因此需要將函數(shù)改造成存儲過程。
存儲過程和函數(shù)的相關(guān)操作
在對儲存過程和函數(shù)操作時,需要首先確認(rèn)用戶是否具有相應(yīng)的權(quán)限。例如,創(chuàng)建存儲過程或者函數(shù)需要CREATE ROUTINE權(quán)限,修改或者刪除存儲過程或者函數(shù)需要ALTER ROUTINE權(quán)限,執(zhí)行過程或者函數(shù)需要EXECUTE權(quán)限
創(chuàng)建一個新的過程 film_in_stock,該過程用來檢查 film_id和store_id對應(yīng)的inventory是否滿足要求,并且返回滿足的inventory_id 以及滿足要求的記錄數(shù)
CREATE PROCEDURE film_in_stock(in p_fim_id int,in p_store_id int,out p_film_count int) READS sql data begin select inventory_id from inventory where film_id =p_film_id and store_id=p_store_id and inventory_in_stock(inventory_id); SELECT found_rows() into p_film_count; end $$
登錄后復(fù)制
通常在創(chuàng)建過程和函數(shù)之前,都會通過DELIMITE $$命令將語句的結(jié)束符從';'修改成其他符號,這里使用‘$$’,這樣在過程和函數(shù)中的';'就不會被MySql,解釋成語句的結(jié)束而錯誤。在存儲過程或者函數(shù)創(chuàng)建完成 通過‘DELIMITER;'命令在將結(jié)束符改回成';'
調(diào)用過程
CALL film_in_stock(2,2,@a);
登錄后復(fù)制
存儲過程的好處在于處理邏輯都封裝在數(shù)據(jù)庫端,調(diào)用者不需要了解中間的處理邏輯,一旦邏輯改變,只需要修改存儲過程,對調(diào)用者的程序沒有影響
刪除存儲過程或者函數(shù)
一次只能刪除一個存儲過程或者函數(shù),刪除需要ALTER ROUTINE權(quán)限
drop procedure film_in_stock;
登錄后復(fù)制
查看存儲過程或者函數(shù)狀態(tài)
show procedure status like 'film_in_stock';
登錄后復(fù)制
查看存儲過程的函數(shù)定義
show create procedure film_in_stock
登錄后復(fù)制
變量使用
存儲過程和函數(shù)中可以使用變量,在MySql 5.1版本中,變量不區(qū)分大小寫
變量的定義
通過DECLARE可以定義一個局部變量,該變量的作用范圍只能在BEGIN...END中,可以用在嵌套塊中
定義一個DATE類型的變量
DECLARE last_month_start date;
登錄后復(fù)制
變量賦值 可以直接賦值,或者通過查詢賦值。直接賦值使用set,可以賦常量或者賦表達(dá)式
set var_name=expr [,var_name=expr]... set last_month_start=date_sub(current_date(),interval month); select col_name[,...] into var_name[,...] table_expr;
登錄后復(fù)制
定義條件和處理
delimiter $$ create procedure actor_insert() begin declare continue handler for sqlstate '23000' set @x2=1; set @x=1; insert into actor(actor_id,first_name,last_name) values(201,'test','201'); set @x=2; insert into actor(actor_id,first_name,last_name) values(1,'test','1'); set @x=3; end ; $$
登錄后復(fù)制
調(diào)用處理函數(shù)時遇到主鍵重的錯誤會按照定義的處理方式去處理,由于定義的是CONTINUE 會繼續(xù)執(zhí)行下面的語句
還支持EXIT表示終止
光標(biāo)使用
聲明光標(biāo)
declare cursor_name cursor for select_statement
open光標(biāo)
open cursor_name
fetch光標(biāo)
fetch cursor_name into var_name[,var_name]...
close光標(biāo)
close cursor_name
delimiter $$
create procedure payment_stat()
begin
declare i_staff_id int;
declare d_amount decimal(5,2);
declare cur_payment cursor for select staff_id,amount from payment;
declare exit handler for not found close cur_payment;
set @x1=0;
set @x2=0;
open cur_payment;
REPEAT
FETCH cur_payment into i_staff_id,d_amount;
if i_staff_id =2 then
set @x1=@x1+d_amount;
else
set @x2=@x2+d_amount;
end if;
until 0 end repeat;
close cur_payment;
end;
$$
登錄后復(fù)制
變量,條件,處理程序,光標(biāo)都是通過DECLARE定義的,她們之間是有先后順序要求的。變量和條件必須在最前面聲明,然后才能是光標(biāo)的聲明,最后才可以是處理程序的聲明
控制語句
case
when i_staff_id =2 then
set @x1=@x1+d_amount;
else
set @x2=@x2+d_amount;
loop 和leave結(jié)合
create procedure actor_insert()
begin
set @x=0;
ins:loop
set @x=@x+1;
if @x=100 then
leave ins;
end if;
insert into actor(first_name,last_name) values('Test','201');
end loop ins;
end;
$$
inerate 語句作用是跳過當(dāng)前循環(huán)的剩下語句,直接進(jìn)入下一輪循環(huán)
create procedure actor_insert()
begin
set @x=0;
ins:loop
set @x=@x+1;
if @x=10 then
leave ins;
elseif mod(@x,2)=0 then
iterate ins;
end if;
insert into actor(actor_id,first_name,last_name) values(@x+200,'test',@x);
end loop ins;
end;
$$
repeat 語句 有條件的循環(huán)控制語句,當(dāng)滿足條件的時候退出循環(huán)
repeat
fetch cur_payment into i_staff_id,d_amount;
if i_staff_id =2 then
set @x1=@x1+d_amount;
else
set @x2=@x2+d_amount;
end if;
until 0 end repeat;
while
delimiter $$
create procedure loop_demo()
begin
set @x=1,@x1=1;
repeat
set @x=@x+1;
until @x>0 end repeat;
while @x<1 do
set @x=@x+1;
end while;
end;
$$
//創(chuàng)建事件調(diào)度器
CREATE EVEN test_event_1 ON SCHEDULE
EVERY 5 SECOND
DO
INSERT INTO dept(deptno,deptname)
VALUES(3,'3');
//查看本地調(diào)度器狀態(tài)
show variables like '%scheduler%';
//打開調(diào)度器
set global event_scheduler=1;
//查看后臺進(jìn)程
show processlist;
//創(chuàng)建一個新的定時器 定時清空表,防止表變大,這類觸發(fā)器非常適合去定期清空臨時表或者日志表
create event trunc_test
on schedule every 1 minute
do truncate table test;
禁用調(diào)度器或者刪除
alter event test_event_1 disable;
drop event test_event_1;
登錄后復(fù)制
| 事件調(diào)度器 | 說明 |
|---|---|
| 優(yōu)勢 | MySQL事件調(diào)度器部署在數(shù)據(jù)庫內(nèi)部由DBA或?qū)H私y(tǒng)一維護(hù)和管理,避免將一些數(shù)據(jù)庫相關(guān)的定時任務(wù)部署到操作系統(tǒng)層,減少操作系統(tǒng)管理員產(chǎn)生誤操作的風(fēng)險,對后續(xù)的管理和維護(hù)也非常有益。例如,后續(xù)進(jìn)行數(shù)據(jù)庫遷移時無需再遷移操作系統(tǒng)層的定時任務(wù),數(shù)據(jù)庫遷移本身已經(jīng)包含了調(diào)度事件的遷移 |
| 使用場景 | 事件調(diào)度器適用于定期收集統(tǒng)計信息,定期清理歷史數(shù)據(jù),定期數(shù)據(jù)庫檢查(例如,自動監(jiān)控和回復(fù)slave失敗進(jìn)程) |
| 注意事項 | 在繁忙且要求性能的數(shù)據(jù)庫服務(wù)器上要慎重部署和啟用調(diào)度去;過于復(fù)雜的處理更適合程序?qū)崿F(xiàn);開啟和關(guān)閉事件調(diào)度器需要具有超級用戶權(quán)限 |
事務(wù)控制和鎖定語句
-
MySQL支持對MyISAM和MEMORY存儲引擎的表進(jìn)行表級鎖定,對InnoDB存儲引擎的表進(jìn)行行集鎖定。默認(rèn)情況下是自動獲得。
-
LOCK TABLES 可以用于鎖定當(dāng)前線程獲得的表,如果表被其他線程鎖定,當(dāng)前線程一直等待到可以獲取現(xiàn)有鎖定為止。
-
UNLOCK TABLES 可以釋放當(dāng)前線程獲得的任何鎖定,當(dāng)前線程執(zhí)行另一個LOCK TABLES時,或當(dāng)與服務(wù)器的連接被關(guān)閉時,所有由當(dāng)前線程鎖定的表被隱式地解鎖。
| session_1 | session_2 |
|---|---|
| 獲取表film_text 的read鎖定 lock table fim_text read | |
| 當(dāng)前seesion可以查詢記錄 select * from fim_text | 其他seesion也可以查詢select * from fim_text |
| 其他session更新鎖定表會等待鎖 update fim_text …. 處于等待狀態(tài) | |
| 釋放鎖 unlock tables | 等待 |
| sesion獲取鎖,更新成功 |
事務(wù)控制
mysql 通過set autocommit ,start transaction ,commit ,rollback等語句支持本地事務(wù)。默認(rèn)情況下,mysql是自動提交(autocommit)的,如果需要明確的commit和rollback來提交和回滾事務(wù),那么就需要通過明確的事務(wù)控制命令來開始事務(wù),這是和Oracle的事務(wù)管理明顯不同的地方。
-
start transaction 或 begin語句可以開始一項新的事務(wù)
-
commit 和rollback用來提交或者回滾事務(wù)。
-
chain和release字句分別用來定義在事務(wù)提交或回滾之后的操作,chain會立即啟動一個新事務(wù),并且和剛才的事務(wù)具有相同的隔離級別,release則會斷開和客戶端的連接。
-
set autocommit可以修改當(dāng)前連接的提交方式,如果設(shè)置了set autocommit=0,則設(shè)置之后的所有事務(wù)讀需要通過明確的命令進(jìn)行提交或者回滾。
如果只是對某些語句需要進(jìn)行事務(wù)控制,則使用start transaction語句開始一個事務(wù)比較方便,這樣事務(wù)結(jié)束之后可以自動回到自動提交的方式,如果希望所有的事務(wù)都不是自動提交的,那么通過修改autocommit來控制事務(wù)比較方便。
start transation和commit and chain
| session_1 | session_2 |
|---|---|
| 從表actor查詢 select * from actor 沒有數(shù)據(jù) | 從表actor查詢 select * from actor 沒有數(shù)據(jù) |
| 啟動一個事務(wù)start transaction; insert into actor… | |
| 查詢actor select * from actor 仍然為空 | |
| commit | |
| 再次查詢 就有 了 select * from actor… |
| session_1 | session_2 |
|---|---|
| 自動提交 inset into actor… | |
| 可以從表中查詢到剛插入 select *from actor | |
| 重新用star transaction 啟動一個事務(wù) start transaction; insert into actor…;用commit and chain命令提交 commit and chain;此時啟動一個新的事務(wù), insert into… | |
| 剛插入的數(shù)據(jù)查不到 select * from actor… | |
| 用commit 提交 commit; | |
| 剛插入的可以查詢到 |
如果在鎖表的期間,用start transaction 命令開始一個新的事務(wù),會造成一個unlock tables被執(zhí)行
| session_1 | session_2 |
|---|---|
| 查詢一個actor_id=201,結(jié)果為空 select * from actor where actor_id=201; | 從表里查詢 同理結(jié)果為空 |
| 對表加寫鎖 lock table actor write | |
| 對表actor 的讀操作被阻塞 select * from actor where actor_id=201 | |
| 插入數(shù)據(jù) insert into actor(actor_id,..)values(201,..) | 等待 |
| 回滾記錄 rollback | 等待 |
| 用start transaction命令重新啟動一個事務(wù) | 等待 |
| 開始一個事務(wù),表鎖被釋放,可以查詢;select …where actor_id=201 | |
| 查到數(shù)據(jù) |
因此,在同一個事務(wù)中,最好不使用不同的存儲引擎,否則rollback時需要對非事務(wù)類型的表進(jìn)行特別的處理。因為,commit ,rollback 只能對事務(wù)類型的表進(jìn)行提交和回滾。
通常情況下,只對提交的事務(wù)記錄到二進(jìn)制的日志中,但是如果一個事務(wù)中包含非事務(wù)類型的表,那么回滾操作也會被記錄到二進(jìn)制日志中,以確保非事務(wù)類型表的更新可以被復(fù)制到從數(shù)據(jù)庫(slave)中。
在事務(wù)中可以通過定義savepoint,指定回滾事務(wù)部分,但是不能指定提交事務(wù)的一個部分。對于復(fù)雜的應(yīng)用,可以定義多個不同的savepoint,滿足不同的條件時,回滾不同的savepoint,需要注意的是,如果定義了相同名字的savepoint,則后面定義的savepoint會覆蓋之前的定義。對于不需要使用的savepoint,可以通過release savepoint命令刪除。
事務(wù)回滾
| session_1 | session_2 |
|---|---|
| 從表中查詢first_name=’Simon’的記錄為空 select * from….where first_name=’simon’ | 從表中查詢first_name=’Simon’的記錄為空 select * from….where first_name=’simon’ |
| 啟動一個事務(wù)插入 一條數(shù)據(jù) start transaction; inset ….values(‘simon’…) | |
| 查詢到剛插入的數(shù)據(jù) select * from…where first_name=’simon’ | 無法從actor查到session1剛插入的記錄 select * from … where first_name=’simon’ |
| 有數(shù)據(jù) | 無數(shù)據(jù) |
| 定義一個 savepoint,名稱為test savepoint test; insert into …values(…,tom) | |
| 查詢到兩條數(shù)據(jù)select *… | 仍然查詢不到數(shù)據(jù) select * … |
| 回滾到剛才定義的savepoint rollback to savepoint test | |
| 從表actor查詢到一條數(shù)據(jù) 第二天被回滾 select * from …. | 仍然查詢不到數(shù)據(jù) |
| 提交commit | |
| 查詢的到 | 查詢的到 |
分布式事務(wù)的使用
MySql從5.0.3開始支持分布式事務(wù),當(dāng)前分布式事務(wù)只支持InnoDb存儲引擎。一個分布式事務(wù)會涉及多個行動,這些行動本身是事務(wù)性。所有行動都必須一起成功完成,或者一起被回滾
在mysql中,使用分布式事務(wù)的應(yīng)用程序涉及一個或多個資源管理器和一個事務(wù)管理器。
-
資源管理器(rm)用于提供通向事務(wù)資源的途徑。數(shù)據(jù)庫服務(wù)器是一種資源管理器,該管理器必須可以提交或回滾由rm管理的事務(wù)。如:多臺mysql數(shù)據(jù)庫作為多臺資源管理器或者幾臺mysql服務(wù)器和幾臺oracle服務(wù)器作為資源管理器。
-
事務(wù)管理器(tm)用于協(xié)調(diào)作為一個分布式事務(wù)一部分的事務(wù)。tm與管理每個事務(wù)的rm s進(jìn)行通信。在分布式事務(wù)中,各個單個事務(wù)均是分布式事務(wù)的“分支事務(wù)”。分布式事務(wù)和各個分支通過一種命名方法進(jìn)行標(biāo)示。
執(zhí)行分布式的過程分為兩階段提交,發(fā)生時間有分布式事務(wù)的各個分支需要進(jìn)行的行動已經(jīng)被執(zhí)行之后
-
在第一階段,所有分支唄預(yù)備好,即它們被TM告知要準(zhǔn)備提交。通常,這意味著用于管理分支的每個RM會記錄對于被穩(wěn)定保存的分支的行動。分支指示是否它們可以這么做,這些結(jié)果被用于第二階段
-
在第二階段,TM告知Rms是否要提交或回滾,如果在預(yù)備分支時,所有的分支指示它們將能夠提交,則所有的分支被告知要提交。如果在預(yù)備時,有任何分支指示它將不能提交,則所有分支唄告知回滾。
語法
xa start xid 用于啟動一個帶給定xid值的xa事務(wù)。每個xa事務(wù)必須有一個唯一的xid值,因此該值當(dāng)前不能被其他xa事務(wù)使用
xa grtid[,beual[,formatId]] grtid 是一個分布式事務(wù)比較符,相同的分布式事務(wù)應(yīng)該使用相同的gtrid,這樣可以明確知道XA事務(wù)屬于哪個分布式事務(wù)
bequal 是一個分支限定符,默認(rèn)值是空值。對于一個分布式事務(wù)中的每個分支事務(wù),bqual指是唯一的
formatId是一個數(shù)值,要用來標(biāo)志 由gtrid和bqual值使用的格式,默認(rèn)是1
xa end xid[suspend [for migrate]] xa prepare xid
登錄后復(fù)制
使事務(wù)進(jìn)入prepare 狀態(tài),也就是兩階段提交的第一個提交階段
xa commit xid[one phase] xa rollback xid
登錄后復(fù)制
用來提交和回滾具體的分支事務(wù)
xa recover 返回當(dāng)前數(shù)據(jù)庫中處于PREPARE狀態(tài)的分支事務(wù)的具體信息
分布式的關(guān)鍵在于如何確保分布式事務(wù)的完整性,以及在某個分支出現(xiàn)問題時的故障解決,xa的相關(guān)命令就是提供給應(yīng)用如何在多個獨立的數(shù)據(jù)庫之間進(jìn)行分布式事務(wù)的管理,包括啟動一個分支事務(wù)、使事務(wù)進(jìn)入準(zhǔn)備階段以及事務(wù)的實際提交回滾操作等,
例子
| session_1 in DB1 | session_2 in DB2 |
|---|---|
| 在數(shù)據(jù)庫DB1 啟動一個分布式的一個分支事務(wù),xid 的gtrid 為 “test”,bqual為”db1”: xa start ‘test’,’db1’;分支事務(wù)插入一個數(shù)據(jù) insert into actor(…)values(…) 對分支事務(wù)1進(jìn)行第一階段提交,進(jìn)入prepare狀態(tài) :xa end ‘test’,’db1’; xa prepare ‘test’,’db1’ | 在數(shù)據(jù)庫DB2 啟動分布式事務(wù) “test”的另外一個分支事務(wù),xid的gtrid為”test”.bqual為”db2”; xa start ‘test’,’db2’: 分支事務(wù)2在表film_actor 更新數(shù)據(jù) 最后 xa end ‘test’,’db2’ xa prepare ‘test’,’db2’ |
| xa recover 查看當(dāng)前分支事務(wù)狀態(tài) | xa recover 查看當(dāng)前分支事務(wù)狀態(tài) |
| 兩個事務(wù)進(jìn)入準(zhǔn)備提交狀態(tài),如果之前遇到任何錯誤,都應(yīng)該回滾到所有分支,以確保事務(wù)的正確 | |
| xa commit ‘test’,’db1’ | xa commit ‘test’,’db2’ |
如果分支事務(wù)在執(zhí)行到prepare狀態(tài)是,數(shù)據(jù)庫異常,且不能再支持啟動,需要備份和binlog來回復(fù)數(shù)據(jù),
SQL Mode
在MySql中,SQLMode常用來解決下面幾類問題
-
通過設(shè)置SQL Mode,可以完成不同嚴(yán)格程度的數(shù)據(jù)校驗,有效的保障數(shù)據(jù)準(zhǔn)確性。
-
通過設(shè)置SQL Mode,為ANSI模式,來保證大多數(shù)SQL符合標(biāo)準(zhǔn)的Sql語法,這樣應(yīng)用在不同數(shù)據(jù)庫之間進(jìn)行遷移時,則不需要對業(yè)務(wù)SQL進(jìn)行較大的修改
-
在不同數(shù)據(jù)庫之間進(jìn)行數(shù)據(jù)遷移之前,通過設(shè)置SQL Mode可以使MySQL上的數(shù)據(jù)更方便地遷移到目標(biāo)數(shù)據(jù)庫中
查看 SQL Mode命令
select @@sql_mode
登錄后復(fù)制
插入一個出國實際定義值的大小varchar(10)
insert into value('123400000000000000000000000000000');
//查看warning內(nèi)容
show warnings
select * from t 這里對插入的數(shù)據(jù)進(jìn)行截取前10位
登錄后復(fù)制
設(shè)置SQL Mode為 嚴(yán)格模式
set session sql_mode='STRICT_TRANS_TABLES'
登錄后復(fù)制
再次插入insert into value('123400000000000000000000000000000'); 直接給出ERROR,而不是warning
SQL Mode常見功能
校驗日期是合法性
set seesion sql_mode='ANSI'
insert into t values('2007-04-31')
登錄后復(fù)制
結(jié)果是 插入值變成'0000-00-00 00:00:00' 并且系統(tǒng)給出warning 而在TRADITIONAL模式下,直接提示日期非法,拒絕插入,同時Mode(x,0)也會報錯
qidon NO_BACKSLASH_ESCAPES模式,使反斜杠成為普通字符,在導(dǎo)入數(shù)據(jù)時,如果數(shù)據(jù)含有反斜杠字符,你們啟動NO_BACKSLASH_ESCAPES模式,保證數(shù)據(jù)的正確性
啟動PIPES_AS_CONCAT。將||視為字符串連接符,在Oracle等數(shù)據(jù)庫中,||被視為字符串的連接操作符,所以在其他數(shù)據(jù)庫中含有||操作符的sql在MySql將無法執(zhí)行,為了解決這個問題mysql提供了PIPES_AS_CONCAT模式、
MySql分區(qū)
MySql從5.1版本開始支持分區(qū),分區(qū)是指按照一定的規(guī)則,數(shù)據(jù)庫把一個表分解成多個更小的,更容易管理的部分。就訪問數(shù)據(jù)庫的應(yīng)用而言,邏輯上只有一個表或一個索引,但是實際上這個表可能由數(shù)10個物理分區(qū)對象組成,每個分區(qū)都是一個獨立的對象,可以獨自處理,可以作為表的一部分進(jìn)行處理。分區(qū)對應(yīng)用而言是完全透明的,不影響應(yīng)用的業(yè)務(wù)邏輯
優(yōu)點
-
和單個磁盤或者文件系統(tǒng)分區(qū)相比,可以存儲更多數(shù)據(jù)
-
優(yōu)化查詢。在where子句中包含分區(qū)條件,可以只掃描必要的一個或多個分區(qū)來提高查詢效率;同時在涉及SUM()和COUNT()這類聚合函數(shù)的查詢時,可以容易的在每個分區(qū)上并行處理,最終只需要匯總所有分區(qū)的結(jié)果
-
對于已經(jīng)過期或者不需要保存的數(shù)據(jù),可以通過刪除與這些數(shù)據(jù)有關(guān)的分區(qū)來快速刪除數(shù)據(jù)
-
跨多個磁盤來分散數(shù)據(jù)查詢,以獲得更大的查詢吞吐量
分區(qū)有利于管理非常大的表,它采用 分而治之的邏輯,分區(qū)引入分區(qū)鍵的概念,分區(qū)鍵用于根據(jù)某個區(qū)間鍵,特定值列表或者HASH函數(shù)執(zhí)行數(shù)據(jù)的聚集,讓數(shù)據(jù)根據(jù)規(guī)則分布在不同的分區(qū)中,讓一個大對象變成一些小對象
show VARIABLES like '%partition%' 查看是否支持分區(qū)
登錄后復(fù)制
Mysql支持大部分存儲引起如MyISAM,INNODb,Memory等存儲引擎,創(chuàng)建分區(qū),在5.1版本中,同一個分區(qū)表的所以分區(qū)必須使用同一個存儲引擎;在同要給表上,不能對一個分區(qū)使用MyISAM引擎和Innodb引擎,但是在同一個MySQL服務(wù)器服務(wù)器上,甚至同一個數(shù)據(jù)庫中,對于不同的分區(qū)表使用不同的存儲引擎
分區(qū)類型
-
range分區(qū):基于一個給定連續(xù)區(qū)間范圍,把數(shù)據(jù)分配到不同的分區(qū)。
-
LIST分區(qū):類似RANGE分區(qū),區(qū)別在LIST分區(qū)是基于枚舉出的值列表分區(qū),RANGE是基于給定的連續(xù)區(qū)間范圍分區(qū)
-
HASH分區(qū):基于給定的分區(qū)個數(shù),把數(shù)據(jù)分配到不同的分區(qū)
-
KEY分區(qū):類似HASH分區(qū)
在5.1版本中,RANGE分區(qū),LIST分區(qū),HASH分區(qū)要求分區(qū)鍵都是int類型,key分區(qū),可以使用其他類型(除了BLOB和TEXT類除外)作為分區(qū)鍵
分區(qū)表的主鍵/唯一鍵必須包含分區(qū)鍵,不能使用主鍵/唯一鍵,要么分區(qū)表的主鍵/唯一鍵都必須包含分區(qū)鍵,分區(qū)的名字是不區(qū)分大小寫的
range分區(qū)
CREATE TABLE emp(
id int not null,
ename varchar(30),
hired date not null DEFAULT '1970-01-01',
separated date NOT null DEFAULT '9999-12-21',
job varchar(30) not null,
store_id int not null
)
partition by range(store_id)(
PARTITION p0 VALUES less than (10),
PARTITION p1 VALUES less than (20),
PARTITION p2 VALUES less than (30)
);
//上述的分區(qū)方案將storid,1-9分到p0區(qū),10-19分到p1區(qū),等如果插入大于30,會出現(xiàn)錯誤,因為沒有規(guī)則保護(hù)大于30的
INSERT into emp VALUES('2322','milk','1993-12-23','1993-12-23','click',19);//可以
//Table has no partition for value 40
INSERT into emp VALUES('2322','milk','1993-12-23','1993-12-23','click',40);
添加分區(qū)
alter table emp add partition(partition p3 values less than maxvalue);
maxvalue表示最大的可能的整數(shù)值
mysql 支持在values less than 語句中加入表達(dá)式
比如以日期作為分區(qū)
CREATE TABLE emp(
id int not null,
ename varchar(30),
hired date not null DEFAULT '1970-01-01',
separated date NOT null DEFAULT '9999-12-21',
job varchar(30) not null,
store_id int not null
)
partition by range(year(separated ))(
PARTITION p0 VALUES less than (1995),
PARTITION p1 VALUES less than (2000),
PARTITION p2 VALUES less than (2005)
);
MySQl 5.5改進(jìn)了range分區(qū)給你,通過支持非整數(shù)分區(qū),創(chuàng)建日期分區(qū)就不需要通過函數(shù)進(jìn)行轉(zhuǎn)換
partition by range(separated )(
PARTITION p0 VALUES less than ('1996-01-01'),
PARTITION p1 VALUES less than ('2001-01-01'),
PARTITION p2 VALUES less than ('2006-01-01')
);
登錄后復(fù)制
rang分區(qū)的功能適用一下情況
- 當(dāng)需要刪除過期的數(shù)據(jù),只需要簡單的alter table emp drop partition p0 來刪除p0 分區(qū)中的數(shù)據(jù)。對于具有上百萬條記錄的表來說,刪除分區(qū)要比運行一個delete語句有效的多
- 經(jīng)常運行包含分區(qū)鍵的查詢,MyySql可以很快地確定只有某一個或者某些分區(qū)需要掃描,因為其他分區(qū)不可能包含有符合該where字句的任何記錄。例如檢索id大于25的記錄數(shù),MySql只需要掃描p2分區(qū)即可
explain partition select count(1) from emp where store_id>=25
登錄后復(fù)制
List分區(qū)
List分區(qū)是建立離散的值列表告訴數(shù)據(jù)庫特定的值屬于哪個分區(qū),LIST分區(qū)在很多方面類似于RANGE分區(qū),區(qū)別在于LIST分區(qū)是從屬于一個枚舉列表,RANGE分區(qū)是從屬于一個連續(xù)區(qū)間值的集合
create table expenses( expense_date date not null, category int, amount decimal(10,3) )partition by list (category)( partition p0 values in(3,5), partition p1 values in(1,10), partition p2 values in(4,9), partition p3 values in(2), partition p4 values in(6) )
登錄后復(fù)制
LIST分區(qū)不存在類似于VALUES LESS THAN MAXVALUE這樣的值 在MYSQL5.5支持非整數(shù)分
Columns分區(qū)
Column分區(qū)是5.5引入的分區(qū)類型,引入Columns分區(qū)解決了MySQL5.5版本之前RANGE和LIST分區(qū)值值支持整數(shù)分區(qū),從而導(dǎo)致需要額外的函數(shù)計算得到整數(shù)值或者通過額外的轉(zhuǎn)換表來轉(zhuǎn)換為整數(shù)在分區(qū)的問題
Column分區(qū)可以細(xì)分為RANGE Columns分區(qū)和LIST Columns分區(qū),RANGE Columns分區(qū)和LIST Columns分區(qū)都支持整數(shù),日期時間,字符串三大數(shù)據(jù)類型
對于Range分區(qū)和List分區(qū),Colums分區(qū)的亮點除了支持?jǐn)?shù)據(jù)類型增加之外,還支持多列分區(qū)
create table rc3(a int,b int) parition by range columns(a,b)( parition p01 values less than(0,10), parition p01 values less than(10,10), parition p01 values less than(10,20), parition p01 values less than(maxvalue,maxvalue) )
登錄后復(fù)制
Hash分區(qū)
hash分區(qū)主要是分?jǐn)?shù)熱點讀,確保數(shù)據(jù)在預(yù)先確定個數(shù)的分區(qū)中盡可能平均分布。對一個表執(zhí)行HASH分區(qū)時,Mysql會對分區(qū)間應(yīng)用一個散列函數(shù),以確定數(shù)在n個分區(qū)中的那個分區(qū)中。
mysql支持兩種hash分區(qū),常規(guī)的hash分區(qū)和線性hash分區(qū),常規(guī)的hash使用取模算法,線性hash分區(qū)使用的一個線性的2的冪的運算法則
create table emp(id int not null.ename varchar(30),hired date not null default '1907-01-01',sparated date null null default '8888-12-31',job varchar(30) not null,store_id int not null) partition by hash(store_id)partitions 4;
登錄后復(fù)制
這里創(chuàng)建了一個常規(guī)的hash 使用 partition by hash(expr)其中expr是某列值或一個整數(shù)值的表達(dá)式返回值。 partition num 對分區(qū)類型,分區(qū)鍵,分區(qū)個數(shù)進(jìn)行定義,上述基于store_id列hash分區(qū),表被分為4個分區(qū)
我們可以計算出它被保存在哪個分區(qū)中假設(shè),假設(shè)記錄的分區(qū)編號為N,那么N=MOD(expr,num),例如emp表中有4個分區(qū),插入一個store_id為234的 mod(234,4)=2,倍保存在第二個分區(qū)
表達(dá)式‘expr’可以是MySQL中有效的任何函數(shù)或者是其他表達(dá)式,只要它們返回一個既非常數(shù)也非隨機數(shù)的整數(shù)。每當(dāng)插入更新刪除一行數(shù)據(jù),這個表達(dá)式就需要計算一次,意味著非常復(fù)雜的表達(dá)式可能會引起性能問題
常規(guī)的HASH分區(qū)通過去模的方式去講數(shù)據(jù)平均分布在每個分區(qū)上,讓每個分區(qū)管理的數(shù)據(jù)都減少,提高了查詢的效率;可是當(dāng)我們需要增加分區(qū)或者合并分區(qū)的時候,問題就出現(xiàn)了,假設(shè)原來是5個常規(guī)hash分區(qū),現(xiàn)在需要新增一個常規(guī)hash分區(qū),原來的去模算法是mod(expr,5)根據(jù)余數(shù)0-4分布在5個分區(qū)上,現(xiàn)在新增一個分區(qū),取模算法變?yōu)閙od(expr,6)根據(jù)余數(shù)0-5分區(qū)在6個分區(qū)中,原來5個分區(qū)的數(shù)據(jù)大部分都需要通過重新計算重新分區(qū),常規(guī)的hash在分區(qū)管理上帶來的代價太大了。不適合靈活變動分區(qū)的需求,Mysql提供了線性hash分區(qū)
create table emp(id int not null.ename varchar(30),hired date not null default '1907-01-01',sparated date null null default '8888-12-31',job varchar(30) not null,store_id int not null) partition by linear hash(store_id)partitions 4; 計算編號為n的分區(qū) 首先找到下一個大于等于num的2的冪,這個值設(shè)為v,v的計算公司 v=power(2,ceiling(log(2,num))) =power(2,ceiling(log(2,4))) =power(2,ceiling(2)) =power(2,2) =4 其次設(shè)置n=f(column_list)&(v-1),現(xiàn)在計算store_id=234對應(yīng)的n值 n=f(column_list)&(4-1) =234&(4-1) =2 當(dāng)n》=num設(shè)置n=n&(v-1) 對于store_id=234由于n=2《4,所以直接判斷這個會被存放到第二分區(qū)
登錄后復(fù)制
線性hash分區(qū)的優(yōu)點在于,在分區(qū)維護(hù)上(包含增加,刪除,合并,拆分分區(qū))時,Mysql能夠處理得更加迅速;缺點是對比常規(guī)hash分區(qū)的時候,線性hash分布不太均衡
key分區(qū)
按照key分區(qū)進(jìn)行分區(qū)非常類似于按照hash進(jìn)行分區(qū),只不過hash分區(qū)允許使用用戶自定義的表達(dá)式,而KEY分區(qū)不行使用用戶自定義的表達(dá)式,需要使用MySQl服務(wù)器提供的hash函數(shù);同時hash分區(qū)只支持整數(shù)分區(qū),而key分區(qū)支持除了blob
or text類型外其他類型的列作為分區(qū)鍵
create table emp(id int not null.ename varchar(30),hired date not null default '1907-01-01',sparated date null null default '8888-12-31',job varchar(30) not null,store_id int not null) partition by key (job)partitions 4; 如果不知道分區(qū)鍵,默認(rèn)為主鍵,沒有主鍵會選擇非空唯一鍵作為分區(qū)鍵
登錄后復(fù)制
子分區(qū)
子分區(qū)是分區(qū)表對每個分區(qū)的再次分割。又被稱為復(fù)合分區(qū),mysql5.1開始支持對已經(jīng)通過range或者list分區(qū)了的表在進(jìn)行子分區(qū)
create table ts(id int,purchased date) partition by range(year(purchased)) subpartition by hash(to_days(purchased))subpartitions 2(partition p0 values less than (1900),partition p0 values less than (2000),partition p0 values less than (maxvalue))
登錄后復(fù)制
在分區(qū)中的null值
在mysql不禁止分區(qū)鍵上使用null,分區(qū)鍵可能是一個字段或者一個用戶定義的表達(dá)式,一般情況下,mysql的分區(qū)把null當(dāng)做零值,或者一個最小值處理
分區(qū)管理
刪除分區(qū) alter table emp_date drop partition p2; 增加分區(qū) alter table emp_date add partition(partition p5 value less than(2025)) 拆分p3分區(qū),分為p2和p3分區(qū) 分區(qū) alter table emp_date reorganize partition p3 into(partition p2 values less than(2005),parition p3 values less than (2015)); 合并分區(qū) alter table emp_date reogranize partition p1,p2,p3 into(partition p1 values less than (2015)) 重新定義list分區(qū)時,只能重新定義相鄰的分區(qū),不能跳過list分區(qū)進(jìn)行重新定義
登錄后復(fù)制
hash&key管理
不能以range和list分區(qū)表刪除分區(qū)的方式,而是跳過alter table coalesce partition 來合并或分區(qū) 以原先4個分區(qū)為例 alter table emp coalesce partition 2 //減少分區(qū)到2個 alter table emp coalesc partition 8 //不能增加分區(qū) 要增加分區(qū) alter table emp add partition partitions 8;
登錄后復(fù)制
相關(guān)推薦:
關(guān)于mysql 基礎(chǔ)知識的總結(jié)
PHP 和 MySQL 基礎(chǔ)教程(一)
PHP 和 MySQL 基礎(chǔ)教程(二)
PHP 和 MySQL 基礎(chǔ)教程(三)
PHP 和 MySQL 基礎(chǔ)教程(四)
mysql手冊教程:http://www.php.cn/course/37.html
mysql視頻教程:http://www.php.cn/course/list/51.html
以上就是mysql基礎(chǔ)知識(mysql新手教程)的詳細(xì)內(nèi)容,更多請關(guān)注風(fēng)君子博客其它相關(guān)文章!
總結(jié)
以上是生活随笔為你收集整理的mysql基础知识(mysql新手教程)(使用方法简单教程)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql group 分页_【MySQ
- 下一篇: MySQL字符串函数:字符串截取总结