mysql的存儲引擎、(存儲過程、視圖)

 

在數據庫中存的就是一張張有着千絲萬縷關係的表,因此表設計的好壞,將直接影響着整個數據庫。而在設計表的時候,咱們都會關注一個問題,使用什麼存儲引擎。等一下,存儲引擎?什麼是存儲引擎?mysql

什麼是存儲引擎?sql

MySQL中的數據用各類不一樣的技術存儲在文件(或者內存)中。這些技術中的每一種技術都使用不一樣的存儲機制、索引技巧、鎖定水平而且最終提供普遍的不一樣的功能和能力。經過選擇不一樣的技術,你可以得到額外的速度或者功能,從而改善你的應用的總體功能。數據庫

例如,若是你在研究大量的臨時數據,你也許須要使用內存MySQL存儲引擎。內存存儲引擎可以在內存中存儲全部的表格數據。又或者,你也許須要一個支持事務處理的數據庫(以確保事務處理不成功時數據的回退能力)。編程

這些不一樣的技術以及配套的相關功能在 MySQL中被稱做存儲引擎(也稱做表類型) MySQL默認配置了許多不一樣的存儲引擎,能夠預先設置或者在MySQL服務器中啓用。你能夠選擇適用於服務器、數據庫和表格的存儲引擎,以便在選擇如何存儲你的信息、如何檢索這些信息以及你須要你的數據結合什麼性能和功能的時候爲你提供最大的靈活性。緩存

關係數據庫表是用於存儲和組織信息的數據結構,能夠將表理解爲由行和列組成的表格,相似於Excel的電子表格的形式。有的表簡單,有的表複雜,有的表根本不用來存儲任何長期的數據,有的表讀取時很是快,可是插入數據時去不好;而咱們在實際開發過程當中,就可能須要各類各樣的表,不一樣的表,就意味着存儲不一樣類型的數據,數據的處理上也會存在着差別,那麼。對於MySQL來講,它提供了不少種類型的存儲引擎(或者說不通的表類型),咱們能夠根據對數據處理的需求,選擇不一樣的存儲引擎,從而最大限度的利用MySQL強大的功能。安全

mysql客戶端中,使用如下命令能夠查看MySQL支持的引擎。服務器

show engines;

 Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
 FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
 MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
 MyISAM             | DEFAULT | MyISAM storage engine                                          | NO           | NO   | NO         |
 BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
 CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
 MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
 ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
 PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
--------------------+---------+----------------------------------------------------------------+--------------+------+------------+

MyISAM網絡

  它不支持事務,也不支持外鍵,尤爲是訪問速度快,對事務完整性沒有要求或者以SELECTINSERT爲主的應用基本均可以使用這個引擎來建立表。
每一個MyISAM在磁盤上存儲成3個文件,其中文件名和表名都相同,可是擴展名分別爲:數據結構

  • .frm(存儲表定義)
  • MYD(MYData,存儲數據)
  • MYI(MYIndex,存儲索引)

  數據文件和索引文件能夠放置在不一樣的目錄,平均分配IO,獲取更快的速度。要指定數據文件和索引文件的路徑,須要在建立表的時候經過DATA DIRECTORYINDEX DIRECTORY語句指定,文件路徑須要使用絕對路徑。
  每一個MyISAM表都有一個標誌,服務器或myisamchk程序在檢查MyISAM數據表時會對這個標誌進行設置。MyISAM表還有一個標誌用來代表該數據表在上次使用後是否是被正常的關閉了。若是服務器覺得當機或崩潰,這個標誌能夠用來判斷數據表是否須要檢查和修復。若是想讓這種檢查自動進行,能夠在啓動服務器時使用--myisam-recover現象。這會讓服務器在每次打開一個MyISAM數據表是自動檢查數據表的標誌並進行必要的修復處理。MyISAM類型的表可能會損壞,可使用CHECK TABLE語句來檢查MyISAM表的健康,並用REPAIR TABLE語句修復一個損壞到MyISAM表。
  MyISAM的表還支持3種不一樣的存儲格式:併發

  • 靜態(固定長度)
  • 動態表
  • 壓縮表

  其中靜態表是默認的存儲格式。靜態表中的字段都是非變長字段,這樣每一個記錄都是固定長度的,這種存儲方式的優勢是存儲很是迅速,容易緩存,出現故障容易恢復;缺點是佔用的空間一般比動態表多。靜態表在數據存儲時會根據列定義的寬度定義補足空格,可是在訪問的時候並不會獲得這些空格,這些空格在返回給應用以前已經去掉。同時須要注意:在某些狀況下可能須要返回字段後的空格,而使用這種格式時後面到空格會被自動處理掉。
  動態表包含變長字段,記錄不是固定長度的,這樣存儲的優勢是佔用空間較少,可是頻繁到更新刪除記錄會產生碎片,須要按期執行OPTIMIZE TABLE語句或myisamchk -r命令來改善性能,而且出現故障的時候恢復相對比較困難。
  壓縮表由myisamchk工具建立,佔據很是小的空間,由於每條記錄都是被單獨壓縮的,因此只有很是小的訪問開支。

InnoDB

InnoDB是一個健壯的事務型存儲引擎,這種存儲引擎已經被不少互聯網公司使用,爲用戶操做很是大的數據存儲提供了一個強大的解決方案。個人電腦上安裝的MySQL 5.6.13版,InnoDB就是做爲默認的存儲引擎。InnoDB還引入了行級鎖定和外鍵約束,在如下場合下,使用InnoDB是最理想的選擇:

1.更新密集的表。InnoDB存儲引擎特別適合處理多重併發的更新請求。
2.事務。InnoDB存儲引擎是支持事務的標準MySQL存儲引擎。
3.自動災難恢復。與其它存儲引擎不一樣,InnoDB表可以自動從災難中恢復。
4.外鍵約束。MySQL支持外鍵的存儲引擎只有InnoDB
5.支持自動增長列AUTO_INCREMENT屬性。

通常來講,若是須要事務支持,而且有較高的併發讀取頻率,InnoDB是不錯的選擇。

MEMORY

使用MySQL Memory存儲引擎的出發點是速度。爲獲得最快的響應時間,採用的邏輯存儲介質是系統內存。雖然在內存中存儲表數據確實會提供很高的性能,但當mysqld守護進程崩潰時,全部的Memory數據都會丟失。得到速度的同時也帶來了一些缺陷。它要求存儲在Memory數據表裏的數據使用的是長度不變的格式,這意味着不能使用BLOBTEXT這樣的長度可變的數據類型,VARCHAR是一種長度可變的類型,但由於它在MySQL內部當作長度固定不變的CHAR類型,因此可使用。

通常在如下幾種狀況下使用Memory存儲引擎:

1.目標數據較小,並且被很是頻繁地訪問。在內存中存放數據,因此會形成內存的使用,能夠經過參數max_heap_table_size控制Memory表的大小,設置此參數,就能夠限制Memory表的最大大小。

2.若是數據是臨時的,並且要求必須當即可用,那麼就能夠存放在內存表中。

3.存儲在Memory表中的數據若是忽然丟失,不會對應用服務產生實質的負面影響。

Memory同時支持散列索引和B樹索引。B樹索引的優於散列索引的是,可使用部分查詢和通配查詢,也可使用<>>=等操做符方便數據挖掘。散列索引進行相等比較很是快,可是對範圍比較的速度就慢多了,所以散列索引值適合使用在=<>的操做符中,不適合在<>操做符中,也一樣不適合用在order by子句中。

能夠在表建立時利用USING子句指定要使用的版本。例如:

複製代碼代碼以下:

create table users
(
    id smallint unsigned not null auto_increment,
    username varchar(15) not null,
    pwd varchar(15) not null,
    index using hash (username),
    primary key (id)
)engine=memory;

 

上述代碼建立了一個表,在username字段上使用了HASH散列索引。下面的代碼就建立一個表,使用BTREE索引。

複製代碼代碼以下:

create table users
(
    id smallint unsigned not null auto_increment,
    username varchar(15) not null,
    pwd varchar(15) not null,
    index using btree (username),
    primary key (id)
)engine=memory;

MERGE

MERGE存儲引擎是一組MyISAM表的組合,這些MyISAM表結構必須徹底相同,儘管其使用不如其它引擎突出,可是在某些狀況下很是有用。說白了,Merge表就是幾個相同MyISAM表的聚合器;Merge表中並無數據,對Merge類型的表能夠進行查詢、更新、刪除操做,這些操做其實是對內部的MyISAM表進行操做。Merge存儲引擎的使用場景。

對於服務器日誌這種信息,通常經常使用的存儲策略是將數據分紅不少表,每一個名稱與特定的時間端相關。例如:能夠用12個相同的表來存儲服務器日誌數據,每一個表用對應各個月份的名字來命名。當有必要基於全部12個日誌表的數據來生成報表,這意味着須要編寫並更新多表查詢,以反映這些表中的信息。與其編寫這些可能出現錯誤的查詢,不如將這些表合併起來使用一條查詢,以後再刪除Merge表,而不影響原來的數據,刪除Merge表只是刪除Merge表的定義,對內部的表沒有任何影響。

ARCHIVE

Archive是歸檔的意思,在歸檔以後不少的高級功能就再也不支持了,僅僅支持最基本的插入和查詢兩種功能。在MySQL 5.5版之前,Archive是不支持索引,可是在MySQL 5.5之後的版本中就開始支持索引了。Archive擁有很好的壓縮機制,它使用zlib壓縮庫,在記錄被請求時會實時壓縮,因此它常常被用來當作倉庫使用。

存儲過程概念

SQL語句須要先編譯而後執行,而存儲過程(Stored Procedure)是一組爲了完成特定功能的SQL語句集,經編譯後存儲在數據庫中,用戶經過指定存儲過程的名字並給定參數(若是該存儲過程帶有參數)來調用執行它。

其相似於函數,就是把一段代碼封裝起來,在封裝的語句中,能夠用if/else while 等控制語句

存儲過程的優勢:

(1).加強SQL語言的功能和靈活性:存儲過程能夠用控制語句編寫,有很強的靈活性,能夠完成複雜的判斷和較複雜的運算。

(2).標準組件式編程:存儲過程被建立後,能夠在程序中被屢次調用,而沒必要從新編寫該存儲過程的SQL語句。並且數據庫專業人員能夠隨時對存儲過程進行修改,對應用程序源代碼毫無影響。

(3).較快的執行速度:若是某一操做包含大量的Transaction-SQL代碼或分別被屢次執行,那麼存儲過程要比批處理的執行速度快不少。由於存儲過程是預編譯的。在首次運行一個存儲過程時查詢,優化器對其進行分析優化,而且給出最終被存儲在系統表中的執行計劃。而批處理的Transaction-SQL語句在每次運行時都要進行編譯和優化,速度相對要慢一些。

(4).減小網絡流量:針對同一個數據庫對象的操做(如查詢、修改),若是這一操做所涉及的Transaction-SQL語句被組織進存儲過程,那麼當在客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句,從而大大減小網絡流量並下降了網絡負載。

(5).做爲一種安全機制來充分利用:經過對執行某一存儲過程的權限進行限制,可以實現對相應的數據的訪問權限的限制,避免了非受權用戶對數據的訪問,保證了數據的安全。

查看存儲過程

mysql> show procedure status;
Empty set (0.16 sec)
mysql>

刪除存儲過程

drop procedure 存儲過程名字

建立存儲過程(delimiter是mysql定義結束標記的,在mysql客戶端中結束標記默認是分號(;)。
若是一次輸入的語句較多,而且語句中間有分號,這時須要新指定一個特殊的結束符。

1建立簡單的存儲過程

 

mysql> select * from name;
+------+-------+-------+
| id   | name  | major |
+------+-------+-------+
|    1 | Jack  | CS    |
|    2 | Paul  | MS    |
|    3 | Linda | SE    |
|    4 | Robin | CS    |
+------+-------+-------+

 

DELIMITER //                               定義結束符

CREATE PROCEDURE test()                   建立test()

BEGIN                                     語句開始標誌

SELECT * FROM name WHERE id = 2;     語句

END//                                     語句結束標誌

DELIMITER ;                              從新定義結束符

  call test();                             調用

效果以下:

mysql> delimiter //
mysql> create procedure test()
    -> begin
    -> select * from name where id = 2;
    -> end//
Query OK, 0 rows affected (0.05 sec)

mysql> delimiter ;
mysql> call test();
+------+------+-------+
| id   | name | major |
+------+------+-------+
|    2 | Paul | MS    |
+------+------+-------+
1 row in set (0.06 sec)

Query OK, 0 rows affected (0.08 sec)

mysql>

二、建立帶有判斷的存儲過程

delimiter //

create procedure test(c char(20))

 begin

select * from car where code = c;

end//

delimiter ;
調用:call test(‘c001’);

效果以下:

mysql> delimiter //
mysql> create procedure test1(c int)
    -> begin
    -> select * from name where id = c;
    -> end//
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> call test1(2);
+------+------+-------+
| id   | name | major |
+------+------+-------+
|    2 | Paul | MS    |
+------+------+-------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.01 sec)

mysql>

二、建立帶有判斷結構的存儲過程

DELIMITER //

CREATE PROCEDURE test(p INT,bs CHAR(10))

    BEGIN

    IF bs = 'da' THEN                          大於的狀況

      SELECT * FROM car WHERE powers > p;

    ELSE                                    小於的狀況

      SELECT * FROM car WHERE powers < p;

    END IF;  

END//

DELIMITER ;

效果以下:

mysql> delimiter //
mysql> create procedure  test2(a int)
    -> begin
    -> if a=2 then
    ->  select * from name where id = 2;
    -> else
    ->  select * from name where id = 1;
    -> end if;
    -> end//
Query OK, 0 rows affected (0.08 sec)

mysql> delimiter ;
mysql> call test2(2);
+------+------+-------+
| id   | name | major |
+------+------+-------+
|    2 | Paul | MS    |
+------+------+-------+
1 row in set (0.04 sec)

Query OK, 0 rows affected (0.06 sec)

二、建立帶有循環的存儲過程

DELIMITER //

CREATE PROCEDURE test(n INT)

BEGIN

    DECLARE SUM INT;     定義變量sum

    DECLARE i INT;        定義變量 i

    SET SUM = 0;         設置sum的值

    SET i = 1;            設置 i 的值

    WHILE i <= n    DO SET SUM = SUM + i;

        SET i = i + 1;

    END WHILE;

    SELECT SUM;        輸出sum

END//

DELIMITER ;

 

調用:CALL test(10);    結果55   

效果以下:

mysql> delimiter //
mysql> create procedure test(n int)
    -> begin
    -> declare sum int;
    -> declare i int;
    -> set sum = 0;
    -> set i = 1;
    -> while i <= n do
    ->      set sum = sum + i;
    ->      set i = i + 1;
    -> end while;
    -> select sum;
    -> end//
Query OK, 0 rows affected (0.06 sec)

mysql> delimiter ;
mysql> call test(10);
+------+
| sum  |
+------+
|   55 |
+------+
1 row in set (0.03 sec)

Query OK, 0 rows affected (0.04 sec)

mysql>

一、視圖的概念

視圖是指計算機數據庫中的視圖,是一個虛擬表,其內容由查詢定義。同真實的表同樣,視圖包含一系列帶有名稱的列和行數據。可是,視圖並不在數據庫中以存儲的數據值集形式存在。行和列數據來自由定義視圖的查詢所引用的表,而且在引用視圖時動態生成

視圖的做用:

A視圖保存的並非真實的數據,而是一張虛擬的表,不佔用內存空間,只是保存了計算須要的sql語句,每次調用的的時候都會本身調用封存的

B提升了安全性能。能夠對不一樣的用戶,設定不一樣的視圖。例如:某用戶只能獲取user表的name和age數據,不能獲取sex數據。則能夠這樣建立視圖

 C提升了重用性,就像一個函數。若是要頻繁獲取user的name和goods的name。就應該使用如下sql語言。

 D讓數據更加清晰。想要什麼樣的數據,就建立什麼樣的視圖。

如下面的三張表爲例:

mysql> select * from exist;
+------+------+------+
| id   | age  | sex  |
+------+------+------+
|    1 |   20 | boy  |
|    2 |   22 | boy  |
|    3 |   21 | girl |
|    4 |   23 | boy  |
+------+------+------+
4 rows in set (0.09 sec)

mysql> select * from score1;
+------+------------+-------+
| id   | course     | score |
+------+------------+-------+
|    1 | math       |    90 |
|    2 | english    |    89 |
|    4 | chinese    |    78 |
|    5 | physical   |    92 |
|    6 | philosophy |    87 |
+------+------------+-------+
5 rows in set (0.05 sec)

mysql> select * from name;
+------+-------+-------+
| id   | name  | major |
+------+-------+-------+
|    1 | Jack  | CS    |
|    2 | Paul  | MS    |
|    3 | Linda | SE    |
|    4 | Robin | CS    |
+------+-------+-------+
4 rows in set (0.05 sec)

建立一個視圖:

mysql> create view aa as select id,name from name;
Query OK, 0 rows affected (0.14 sec)

mysql>

使用一個視圖: 使用視圖和使用表徹底同樣,只須要把視圖當成一張表就OK了。

查看視圖和表:

mysql> show tables;
+-----------------+
| Tables_in_ceshi |
+-----------------+
| aa              |
| course          |
| exist           |
| name            |
| score           |
| score1          |
| student         |
| teacher         |
+-----------------+
8 rows in set (0.17 sec)

mysql>

查看視圖詳細信息:

mysql> desc aa;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.07 sec)

mysql>
mysql> select * from aa;
+------+-------+
| id   | name  |
+------+-------+
|    1 | Jack  |
|    2 | Paul  |
|    3 | Linda |
|    4 | Robin |
+------+-------+
4 rows in set (0.00 sec)

mysql>

修改視圖

mysql> create or replace view aa as select * from name;
Query OK, 0 rows affected (0.08 sec)

mysql> select * from aa;
+------+-------+-------+
| id   | name  | major |
+------+-------+-------+
|    1 | Jack  | CS    |
|    2 | Paul  | MS    |
|    3 | Linda | SE    |
|    4 | Robin | CS    |
+------+-------+-------+
4 rows in set (0.00 sec)

mysql>

二、視圖與表之間的增刪改

   當表增刪改時,視圖也會相應的增刪改

效果以下:

 

mysql> update  name set id = 5 where major = "cs";
Query OK, 2 rows affected (0.06 sec)
Rows matched: 2  Changed: 2  Warnings: 0

mysql> select * from name;
+------+-------+-------+
| id   | name  | major |
+------+-------+-------+
|    5 | Jack  | CS    |
|    2 | Paul  | MS    |
|    3 | Linda | SE    |
|    5 | Robin | CS    |
+------+-------+-------+
4 rows in set (0.00 sec)

mysql> select * from aa;
+------+-------+-------+
| id   | name  | major |
+------+-------+-------+
|    5 | Jack  | CS    |
|    2 | Paul  | MS    |
|    3 | Linda | SE    |
|    5 | Robin | CS    |
+------+-------+-------+
4 rows in set (0.00 sec)

mysql>

 

 

 

   當視圖增刪改時,要分兩種狀況

   第一種:視圖是單表查詢出的結果時,能夠增刪改

 

mysql> select * from name;
+------+-------+-------+
| id   | name  | major |
+------+-------+-------+
|    5 | Jack  | CS    |
|    2 | Paul  | MS    |
|    3 | Linda | SE    |
|    5 | Robin | CS    |
+------+-------+-------+
4 rows in set (0.00 sec)

mysql> select * from aa;
+------+-------+-------+
| id   | name  | major |
+------+-------+-------+
|    5 | Jack  | CS    |
|    2 | Paul  | MS    |
|    3 | Linda | SE    |
|    5 | Robin | CS    |
+------+-------+-------+
4 rows in set (0.00 sec)

mysql> select * from name;
+------+-------+-------+
| id   | name  | major |
+------+-------+-------+
|    5 | Jack  | CS    |
|    2 | Paul  | MS    |
|    3 | Linda | SE    |
|    5 | Robin | CS    |
+------+-------+-------+
4 rows in set (0.05 sec)

mysql> update aa set id = 1 where name="jack";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from aa;
+------+-------+-------+
| id   | name  | major |
+------+-------+-------+
|    1 | Jack  | CS    |
|    2 | Paul  | MS    |
|    3 | Linda | SE    |
|    5 | Robin | CS    |
+------+-------+-------+
4 rows in set (0.00 sec)

mysql> select * from name;
+------+-------+-------+
| id   | name  | major |
+------+-------+-------+
|    1 | Jack  | CS    |
|    2 | Paul  | MS    |
|    3 | Linda | SE    |
|    5 | Robin | CS    |
+------+-------+-------+
4 rows in set (0.00 sec)

mysql>

   第二種:視圖是多表查詢出的結果時,不能夠增刪改

 

mysql> create view a as select * from score1 left join name on score1.id = name.id;
ERROR 1060 (42S21): Duplicate column name 'id'
mysql>
相關文章
相關標籤/搜索