資料庫基礎知識詳解四:儲存過程、檢視、遊標、SQL語句優化以及索引

投三分的金閃閃發表於2022-04-12

寫在文章前:本系列文章用於博主自己歸納複習一些基礎知識,同時也分享給可能需要的人,因為水平有限,肯定存在諸多不足以及技術性錯誤,請大佬們及時指正。

11、儲存過程

儲存過程是事先經過編譯並儲存在資料庫中的一段SQL語句的集合。想要實現相應的功能時,只需要呼叫這個儲存過程就行了(類似於函式,輸入具有輸出引數)。

優點

  • 預先編譯,而不需要每次執行時編譯,提高了資料庫執行效率。
  • 封裝了一系列操作,對於一些資料互動比較多的操作,相比於單獨執行SQL語句,可以減少網路通訊量。
  • 具有可複用性,減少了資料庫開發的工作量。
  • 安全性高,可以讓沒有許可權的使用者通過儲存過程間接運算元據庫。
  • 更易於維護。

缺點

  • 可移植性差,儲存過程將應用程式繫結到了資料庫上。
  • 開發除錯複雜。
  • 修改複雜,需要重新編譯,有時還需要更新程式中的程式碼以更新呼叫。

Drop/Delete/Truncate的區別?

Delete用來刪除表的全部或者部分資料,執行delete之後,使用者需要提交之後才會執行,會觸發表上的DELETE觸發器(包含一個OLD的虛擬表,可以只讀訪問被刪除的資料),DELETE之後表結構還在,刪除很慢,一行一行地刪,因為會記錄日誌,可以利用日誌還原資料;

Truncate刪除表中的所有資料,這個操作不能回滾,也不會觸發這個表上的觸發器。操作比DELETE快很多(直接把表drop掉,再建立一個新表,刪除的資料不能找回)。如果表中有自增(AUTO_INCREMENT)列,則重置為1。

Drop命令從資料庫中刪除表,所有的資料行,索引和約束都會被刪除。不能回滾,不會觸發觸發器。

觸發器是什麼?

觸發器(TRIGGER)是由事件(比如INSERT/UPDATE/DELETE)來觸發執行的操作(不能被直接呼叫,不能接收引數)。在資料庫裡以獨立的物件儲存,用於保證資料完整性(比如可以檢驗或轉換資料)。

有哪些約束型別?

約束(Constraint)型別:

  • 主鍵(Primary Key)約束
  • 唯一約束(Unique)
  • 檢查約束
  • 非空約束
  • 外來鍵(Foreign Key)約束

12、檢視、遊標

檢視

​ 從資料庫的基本表中通過查詢選取出來的資料組成的虛擬表(資料庫中只存放檢視的定義,而不存放檢視的資料)。可以對其進行增/刪/改/查等操作。檢視是對若干張基本表的引用,一張虛表,查詢語句執行的結果,不儲存具體的資料(基本表資料發生了改變,檢視也會跟著改變)。

可以跟基本表一樣,進行增刪改查操作(增刪改操作有條件限制,一般檢視只允許查詢操作),對檢視的增刪改也會影響原表的資料。它就像一個視窗,透過它可以看到資料庫中自己感興趣的資料並且操作它們。好處:

  • 通過只給使用者訪問檢視的許可權,保證資料的安全性。
  • 可以通過對不同的使用者定義不同的檢視,使機密資料不出現在不應該看到這些資料的使用者檢視上。例如,Student表涉及全校15個院系學生資料,可以在其上定義15個檢視,每個檢視只包含一個院系的學生資料,並只允許每個院系的主任查詢和修改本原系學生檢視。
  • 可以通過檢視使使用者以多種角度看待同一資料,比如不同種類的使用者共享一個資料庫。(通過許可權?)
  • 簡化複雜的SQL操作(比如原來查的內容是幾張幾百列的資料表,而我們只關心其中幾個資料,那我們可以建立一個檢視,直接在檢視中查詢它們,可以提高很多效率),隱藏資料的複雜性(比如複雜的連線)。

遊標(Cursor)

​ 用於定位在查詢返回的結果集的特定行,以對特定行進行操作。使用遊標可以方便地對結果集進行移動遍歷,根據需要滾動或對瀏覽/修改任意行中的資料。主要用於互動式應用。它是一段私有的SQL工作區,也就是一段記憶體區域,用於暫時存放受SQL語句影響的資料,簡單來說,就是將受影響的資料暫時放到了一個記憶體區域的虛表當中,這個虛表就是遊標。

​ 遊標是一種能從包括多條資料記錄的結果集中每次提取一條記錄的機制。即遊標用來逐行讀取結果集。遊標充當指標的作用。儘管遊標能遍歷結果中的所有行,但他一次只指向一行。

​ 遊標的一個常見用途就是儲存查詢結果,以便以後使用。遊標的結果集是由SELECT語句產生,如果處理過程需要重複使用一個記錄集,那麼建立一次遊標而重複使用若干次,比重複查詢資料庫要快的多。通俗來說,遊標就是能在sql的查詢結果中,顯示某一行(或某多行)資料,其查詢的結果不是資料表,而是已經查詢出來的結果集。

簡單來說:遊標就是在查詢出的結果集中進行選擇性操作的工具。

13、SQL語句的優化

  • 應儘量避免在 where 子句中使用!=、<、>操作符或對欄位進行null值判斷,否則將引擎放棄使用索引而進行全表掃描;
  • 只返回必要的列:最好不要使用 SELECT * 語句;
  • 只返回必要的行:使用 LIMIT 語句來限制返回的資料;
  • 將一個大連線查詢分解成對每一個表進行一次單表查詢,然後進行關聯,這樣做的好處有:

​ 讓快取更高效。對於連線查詢,如果其中一個表發生變化,那麼整個查詢快取就無法使用。而分解後的多個查詢,即使其中一個表發生變化,對其它表的查詢快取依然可以使用。分解成多個單表查詢,這些單表查詢的快取結果更可能被其它查詢使用到,從而減少冗餘的查詢。減少鎖競爭。

14、索引

​ 索引是對資料庫表中一列或多列的值進行排序的一種結構(說明是在列上建立的),使用索引可快速訪問資料庫表中的特定資訊。如果想按特定職員的姓來查詢他或她,則與在表中搜尋所有的行相比,索引有助於更快地獲取資訊。索引的一個主要目的就是加快檢索表中資料,亦即能協助資訊搜尋者儘快的找到符合限制條件的記錄ID的輔助資料結構。

​ 當表中有大量記錄時,若要對錶進行查詢,第一種搜尋資訊方式是全表搜尋,是將所有記錄一一取出,和查詢條件進行一一對比,然後返回滿足條件的記錄,這樣做會消耗大量資料庫系統時間,並造成大量磁碟I/O操作。第二種就是在表中建立索引,然後在索引中找到符合查詢條件的索引值,最後通過儲存在索引中的ROWID(相當於頁碼)快速找到表中對應的記錄。

例如這樣一個查詢:select * from table1 where id=10000。如果沒有索引,必須遍歷整個表,直到ID等於10000的這一行被找到為止。有了索引之後(必須是在ID這一列上建立的索引),即可在索引中查詢。由於索引是經過某種演算法優化過的,因而查詢次數要少的多。可見,索引是用來定位的。

  • (1)聚簇索引對磁碟上存放資料的實體地址重新組織以使這些資料按照指定規則排序的一種索引(資料的物理排列順序和索引排列順序一致)。按照資料存放的物理位置為順序,每張資料表只能建立一個聚簇索引(因為要改變物理儲存順序),與非聚簇索引相比查詢資料速度很快,進行修改的速度較慢。主鍵索引就是一種聚簇索引。
  • InnoDB表要求必須有聚簇索引,預設在主鍵欄位上建立聚簇索引,在沒有主鍵欄位的情況下,表的第一個NOT NULL 的唯一索引將被建立為聚簇索引,在前兩者都沒有的情況下,InnoDB將自動生成一個隱式自增id列並在此列上建立聚簇索引。
  • (2)非聚簇索引(也叫二級索引/輔助索引)只記錄邏輯順序,並不改變物理順序。通過索引記錄地址訪問表中的資料。索引的邏輯順序和表中行的物理儲存順序不同。Innodb使用的是聚簇索引,MyISam使用的是非聚簇索引。

從應用上分,主鍵索引(聚集)唯一索引(聚集/非聚集)普通索引組合索引單列索引和全文索引

  • (3)唯一索引(UNIQUE):索引列的值必須唯一,允許有空值。
  • (4)主鍵索引 PRIMARY KEY:必須唯一,不允許空值(是一種特殊的唯一索引。表中只有一個,MySQL建立主鍵時預設為聚集索引,但主鍵也可以是非聚集索引)。當列新增主鍵約束時,自動新增主鍵索引。
  • (5)普通索引:用表中的普通列構建的索引,沒有任何限制,用於加速查詢。
  • (6)組合索引(複合索引):多列值組成一個索引,專門用於組合搜尋,其效率大於索引合併。
  • (7)全文索引:先定義一個詞庫,然後在文章中查詢每個詞條(term)出現的頻率和位置,把這樣的頻率和位置資訊按照詞庫的順序歸納,這樣就相當於對檔案建立了一個以詞庫為目錄的索引,這樣查詢某個詞的時候就能很快的定位到該詞出現的位置。

索引的優點

  • 大大加快了資料的檢索速度。
  • 顯著減少查詢中分組和排序的時間。
  • 通過建立唯一性索引,可以保證資料庫表中的某一行資料的唯一性。
  • 將隨機I/O變為了順序I/O(B+Tree 索引是有序的,會將相鄰的資料都儲存在一起)。

索引的缺點

  • 建立和維護索引組要耗費時間,並且隨著資料量的增加所耗費的時間也會增加。
  • 索引需要佔磁碟空間,除了資料表佔資料空間以外,每一個索引還要佔一定的物理空間。如果有大量的索引,索引檔案可能比資料檔案更快達到最大檔案尺寸。
  • 當對錶中的資料進行增加、刪除和修改的時候,索引也要動態維護,這樣就降低了資料的維護速度。

索引失效的情況?

  • 以“%(表示任意0個或多個字元)”開頭的LIKE語句。
  • OR條件中的每個列沒有同時使用索引。
  • 對於多列索引,必須滿足 最左匹配原則/最左字首原則 (最左優先:多列索引col1、col2和col3,則 索引生效的情形包括 col1或col1,col2或col1,col2,col3)。
  • 如果MySQL估計全表掃描比索引快,則不使用索引(比如非常小的表)。

哪些地方適合建立索引?

  • 某列經常作為最大最小值。
  • 經常被查詢的欄位。
  • 經常用作表連線的欄位。
  • 經常出現在ORDER BY/GROUP BY/DISDINCT後面的欄位。

建立索引需要注意的

  • 只應建立在小欄位上,而不要對大文字或圖片建立索引(一頁儲存的資料越多一次IO操作獲取的資料越大效率越高)。

  • 建立索引的欄位應該非空,在MySQL中,含有空值的列很難進行查詢優化,因為它們使得索引、索引的統計資訊以及比較運算更加複雜。應該用0、一個特殊的值或者一個空串代替NULL。

  • 選擇資料密度大(唯一值佔總數的百分比很大)的欄位作索引。

相關文章