程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> MySQL數據庫中索引的創建與刪除

MySQL數據庫中索引的創建與刪除

編輯:MySQL綜合教程

以下的文章主要是對MySQL數據庫的創建與刪除,以及索引與更改實際表語句的詳細解析,如果你也是MySQL數據庫的熱捧著的話,你就可以點擊以下的文章對其有一個更好的了解,以下就是文章的具體內容。

一、創建、刪除、索引和更改表

可利用CREATE TABLE、DROP TABLE 和ALTER TABLE 語句創建表,然後,對它們進行刪除,更改它們的結構。對於它們中的每一條語句,存在MySQL數據庫專有的擴充,這些擴充使各語句更為有用。CREATE INDEX 和DROP INDEX 語句使您能夠增加或刪除現有表上

的索引。

二、CREATE TABLE 語句

用CREATE TABLE 語句創建表。此語句的完整語法是相當復雜的,因為存在那麼多的可選子句,但在實際中此語句的應用相當簡單。如我們在第1章中使用的所有CREATE TABLE 語句都不那麼復雜。有意思的是,大多數復雜東西都是一些子句,這些子句MySQL數據庫在分析後扔掉。參閱附錄D 可看到這些復雜的東西。

看看CREATE TABLE 語句的各項條款,注意該語句有多少語法是用於REFERENCES CONSTRAINT 和CHECK 子句的。這些子句涉及外部鍵、引用完整性及輸入值約束。MySQL不支持這些功能,但它分析其語法使其更容易利用在其他數據庫系統中建立的表定義。可以 用較少的編輯工作更容易地利用該代碼。)

如果您從頭開始編寫自己的表描述,可以完全不管這些子句。本節中我們對它們也不多做介紹。CREATE TABLE 至少應該指出表名和表中列的清單。例如:

除構成表的列以外,在創建表時還可以說明它應該怎樣索引。另一個選擇是創建表時不進行索引,以後再增加索引。如果計劃在開始將表用於查詢前,用大量的數據 填充此表,以後再創建索引是一個好辦法。在插入每一行時更新索引較裝載數據到一個未索引的表中然後

再創建索引要慢得多。我們已經在第1章中介紹了 CREATE TABLE 語句的基本語法,並在第2章討論了怎樣描述列類型。這裡假定您已經讀過了這兩章,因此我們就不重復這些內容了。在本節下面,我們將介紹一些 MySQL3.23 中對CREATE TABLE 語句的重要擴充,這些擴充在構造表方面提供了很大的靈活性,這些擴充為:

表存儲類型說明符。

僅當表不存在時才進行創建。

在客戶機會話結束時自動刪除臨時表。

通過選擇希望表存儲的數據來創建一個表。

1. 表存儲類型說明符

在MySQL3.23 之前,所有用戶創建的表都利用的是ISAM 存儲方法。在MySQL3.23中,可在CREATE TABLE 語句的列的列表之後指定TYPE = type,以三種類型明確地創建表。其中type 可以為MYISAM、ISAM 或HEAP。例如:

將表轉換為HEAP 類型可能不是一個好主意,但是,如果希望表一直維持到服務器關閉,可以進行這個轉換。HEAP 表在服務器退出之前,一直保留在內存中。這三種表類型的一般特點如下:

MyISAM 表。MyISAM 存儲格式自版本3.23 以來是MySQL數據庫中的缺省類型,它有下列特點:

如果操作系統自身允許更大的文件,那麼文件比ISAM 存儲方法的大。

數據以低字節優先的機器獨立格式存儲。這表示可將表從一種機器拷貝到另一種機器,即使它們的體系結構不同也可以拷貝。

數值索引值占的存儲空間較少,因為它們是按高字節優先存儲的。索引值在低位字節中變化很快,因此高位字節更容易比較。

AUTO_INCREMENT 處理比ISAM 的表更好。詳細內容在第2章討論。

減少了幾個索引限制。例如,可對含NULL 值的列進行索引,還可以對BLOB 和TEXT 類型的列進行索引。

為了改善表的完整性檢查,每個表都具有一個標志,在myisamchk 對表進行過檢查後,設置該標志。可利用myisamchk – fast 跳過對自前次檢查以來尚未被修改過表的檢查,這樣使此管理任務更快。表中還有一個指示表是否正常關閉的標志。如果服務器關閉不正常,或機器崩潰,此標志可 用來檢測出服務器起動時需要檢查的表。

ISAM 表。ISAM 存儲格式是MySQL3.23 所用的最舊的格式,但當前仍然可用。通常,相對於ISAM 表來說,寧可使用MyISAM 表,因為它們的限制較少。對ISAM 表的支持隨著此存儲格式被MyISAM 表格式所支持很有可能會逐漸消失。

HEAP 表。HEAP 存儲格式建立利用定長行的內存中的表,這使表運行得非常快。在服務器停止時,它們將會消失。在這種意義上,這些表是臨時的。但是,與用CREATE TEMPORARY TABLE 所創建的臨時表相比,HEAP 表是其他客戶機可見的。HEAP 表有幾個限制,這些限制對MyISAM 或ISAM 表沒有,如下所示:

索引僅用於“=”和“< = >”比較。

索引列中不能有NULL 值。

不能使用BLOB 和TEXT 列。

不能使用AUTO_INCREMENT 列。

2. 創建不存在的表

要創建一個不存在的表,使用CREATE TABLE IF NOT EXISTS 即可。在某種應用程序中,無法確定要用的表是否已經存在,因此,要創建這種表。IF NOT EXISTS 修飾符對於作為用MySQL運行的批量作業的腳本極為有用。在這裡,普通的CREATE TABLE 語句工作得

不是很好。因為作業第一次運行 時,建立這些表,如果這些表已經存在,則第二次運行時將出錯。如果用IF NOT EXISTS語句,就不會有問題。每一次運行作業時,像前面一樣創建表。如果這些表已經存在,在第二次運行時,創建表失敗,但不出錯。這使得作業可以繼續 運行,就像創建表的企圖已經成功了一樣。

3. 臨時表

可用CREATE TEMPORARY TABLE 來創建臨時表,這些表在會話結束時會自動消失。使用臨時表很方便,因為不必費心發布DROP TABLE 語句明確地刪除這些表,而且如果您的會話不正常結束,這些表不會滯留。例如,如果某個文件中有一個用MySQL數據庫運行的查詢,您決定不等到其結束,那麼可以 在其執行的中途停止這個查詢,而且毫無問題,服務器將刪除所創建的任意臨時表。在舊版的MySQL中,沒有真正的臨時表,除了您在自己的頭腦中認為它們是 臨時的除外。

對於需要這樣的表的應用程序,必須自己記住刪除這些表。如果忘了刪除,或在前面使其存在的客戶機中出現錯誤時,這些表在有人注意到並刪除它們 以前會一直存在。臨時表僅對創建該表的客戶機可見。其名稱可與一個現有的永久表相同。這不是錯誤,也不會使已有的永久表出問題。

假如在samp_db 數據庫中創建了一個名為member 的臨時表。原來的member 表變成隱藏的不可訪問),對member 的引用將引用臨時表。如果發布一條DROP TABLE member 語句,這個臨時表將被刪除,而原來的member 表“重新出現”。如果您簡單地中斷與服務器的連接而沒有刪除臨時表,服務器會自動地刪除它。下一次連接時,

原來的member 表再次可見。名稱隱藏機制僅在一個級別上起作用。即,不能創建兩個具有同一個名稱的臨時表。

4. 利用SELECT 的結果創建表

關系數據庫的一個重要概念是,任何數據都表示為行和列組成的表,而每條SELECT 語句的結果也都是一個行和列組成的表。在許多情況下,來自SELECT 的“表”僅是一個隨著您的工作在顯示屏上滾動的行和列的圖像。在MySQL3.23 以前,如果想將SELECT 的結果保存在一個表中以便以後的查詢使用,必須進行特殊的安排:

1) 運行DESCRIBE 或SHOW COLUMNS 查詢以確定想從中獲取信息的表中的列類型。

2) 創建一個表,明確地指定剛才查看到的列的名稱和類型。

3) 在創建了該表後,發布一條INSERT … SELECT 查詢,檢索出結果並將它們插入所創建的表中。

在MySQL3.23 中,全都作了改動。CREATE TABLE … SELECT 語句消除了這些浪費時間的東西,使得能利用SELECT 查詢的結果直接得出一個新表。只需一步就可以完成任務,不必知道或指定所檢索的列的數據類型。這使得很容易創建一個完全用所喜歡的數據填充的表,並且為進 一步查詢作了准備。

可以通過選擇一個表的全部內容無WHERE 子句)來拷貝一個表,或利用一個總是失

敗的WHERE 子句來創建一個空表,如:

如果希望利用LOAD DATA 將一個數據文件裝入原來的文件中,而不敢肯定是否具有指定的正確數據格式時,創建空拷貝很有用。您並不希望在第一次未得到正確的選項時以原來表中畸形的記 錄而告終。

利用原表的空拷貝允許對特定的列和行分隔符用LOAD DATA 的選項進行試驗,直到對輸入數據的解釋滿意時為止。在滿意之後,就可以將數據裝入原表了。

可結合使用CREATE TEMPORARY TABLE 與SELECT 來創建一個臨時表作為它自身的拷貝,如:

這允許修改my_tbl 的內容而不影響原來的內容。在希望試驗對某些修改表內容的查詢,而又不想更改原表內容時,這樣做很有用。為了使用利用原表名的預先編寫的腳本,不需要為引 用不同的表而編輯這些腳本;只需在腳本的起始處增加CREATE TEMPORARY TABLE語句即可。相應的腳本將創建一個臨時拷貝,並對此拷貝進行操作,當腳本結束時服務器會自動刪除這個拷貝。

要創建一個作為自身的空拷貝的表,可以與CREATE TEMPORARY … SELECT 一起使用WHERE 0 子句,例如:

但創建空表時有幾點要注意。在創建一個通過選擇數據填充的表時,其列名來自所選擇的列名。如果某個列作為表達式的結果計算,則該列的“名稱”為表達式的文 本。表達式不是合法的列名,可在MySQL數據庫中運行下列查詢了解這一點:

如果選擇了來自不同表的具有相同名稱的列,將會出現一定的困難。假定表t1和t2 兩者都具有列c,而您希望創建一個來自兩個表中行的所有組合的表。

那麼可以提供別名指定新表中惟一性的列名,如:

通過選擇數據進行填充來創建一個表並會自動拷貝原表的索引。

3、 DROP TABLE 語句

刪 除表比創建表要容易得多,因為不需要指定有關其內容的任何東西;只需指定其名稱即可,如:

  1. DROP TABLE tb1_name 

MySQL對DROP TABLE 語句在某些有用的方面做了擴充。首先,可在同一語句中指定幾個表對它們進行刪除,如:

  1. DROP TABLE tb1_name1,tb1_name2,…… 

其次,如果不能肯定一個表是否存在,但希望如果它存在就刪除它。那麼可在此語句中增加IF EXISTS。這樣,如果DROP TABLE 語句中給出的表不存在,MySQL不會發出錯誤信息。如:

  1. DROP TABLE IF EXISTS tb1_name 

IF EXISTS 在MySQL所用的腳本中很有用,因為缺省情況下, MySQL將在出錯時退出。例如,有一個安裝腳本能夠創建表,這些表將在其他腳本中繼續使用。在此情形下,希望保證此創建表的腳本在開始運行時無後顧之 憂。如果在該腳本開始處使用普通的DROP TABLE,那麼它在第一次運行時將會失敗,因為這些表從未創建過。如果使用IF EXISTS,就不會產生問題了。當表已經存在時,將它們刪除;如果不存在,腳本繼續運行。

四. 創建和刪除索引

索引是加速表內容訪問的主要手段,特別對涉及多個表的連接的查詢更是如此。這是第4章“查詢優化”中的一個重要內容,第4章討論了為什麼需要索引,索引如 何工作以及怎樣利用它們來優化查詢。本節中,我們將介紹索引的特點,以及創建和刪除索引的語法。

1. 索引的特點

MySQL對構造索引提供了很大的靈活性。可對單列或多列的組合進行索引。如果希望能夠從一個表的不同列中找出一個值,還可以在一個表上構造不止一個索 引。如果某列為串類型而非ENUM 或SET 類型,可以選擇只對該列最左邊的n 個字符進行索引。如果該列的前n個字符最具有唯一性,這樣做一般不會犧牲性能,而且還會對性能有大的改善:用索引列的前綴而非整個列可使索引更小且訪問更 快。雖然隨著MySQL數據庫的進一步開發創建索引的約束將會越來越少,但現在還是存在一些約束的。下面的表根據索引的特性,給出了ISAM 表和MyISAM 表之間的差別:

從此表中可以看到,對於ISAM 表來說,其索引列必須定義為NOT NULL,並且不能對BLOB 和TEXT 列進行索引。MyISAM 表類型去掉了這些限制,而且減緩了其他的一些限制。兩種表類型的索引特性的差異表明,根據所使用的MySQL版本的不同,有可能對某些列不能進行索引。例 如,如果使用3.23 版以前的版本,則不能對包含NULL 值的列進行索引。

如果使用的是MySQL3.23版或更新的版本,但表是過去以ISAM 表創建的,可利用ALTER TABLE 很方便地將它們轉換為MyISAM 存儲格式,這樣使您能利用某些較新的索引功能,如:

ALTER TABLE tb1_name TYPE=MYISAM

2. 創建索引

在執行CREATE TABLE 語句時,可為新表創建索引,也可以用CREATE INDEX 或ALTER TABLE 來為一個已有的表增加索引。CREATE INDEX 是在MySQL3.23版中引入的,但如果使用3.23 版以前的版本,可利用ALTER TABLE 語句創建索引MySQL通常在內部將CRE ATE INDEX 映射到ALTER TABLE)。可以規定索引能否包含重復的值。如果不包含,則索引應該創建為PRIMARY KEY 或UNIQUE 索引。對於單列惟一索引,這保證了列不包含重復的值。對於多列惟一索引,它保證值的組合不重復。

PRIMARY KEY 索引和UNIQUE 索引非常類似。事實上, PRIMARY KEY 索引僅是一個具有名稱PRIMARY 的UNIQUE 索引。這表示一個表只能包含一個PRIMARY KEY,因為一個表中不可能具有兩個同名的索引。同一個表中可有多個UNIQUE 索引,雖然這樣做意義不

大。

為了給現有的表增加一個索引,可使用ALTER TABLE 或CREATE INDEX 語句。ALTER TABLE 最常用,因為可用它來創建普通索引、UNIQUE 索引或PRIMARY KEY 索引,如:

其中tbl_name 是要增加索引的表名,而column_list 指出對哪些列進行索引。如果索引由不止一列組成,各列名之間用逗號分隔。索引名index_name 是可選的,因此可以不寫它,MySQL將根據第一個索引列賦給它一個名稱。ALTER TABLE 允許在單個語句中指定多個表的更改,因此可以在同時創建多個索引。

CREATE INDEX 可對表增加普通索引或UNIQUE 索引,如:

tbl _ name、index_name 和column_list 具有與ALTER TABLE 語句中相同的含義。這裡索引名不可選。不能用CREATE INDEX 語句創建PRIMARY KEY 索引。要想在發布CREATE TABLE 語句時為新表創建索引,所使用的語法類似於ALTER TABLE 語句的語法,但是應該在您定義表列的語句部分指定索引創建子句,如下所示:

與ALTER TABLE 一樣,索引名對於INDEX 和UNIQUE 都是可選的,如果未給出,MySQL數據庫將為其選一個。有一種特殊情形:可在列定義之後增加PRIMARY KEY 創建一個單列的PRIMARY KEY索引,如下所示:

前面所有表創建樣例都對索引列指定了NOT NULL。如果是ISAM 表,這是必須的,因為不能對可能包含NULL 值的列進行索引。如果是MyISAM 表,索引列可以為NULL,只要該索引不是PRIMARY KEY 索引即可。

如果對某個串列的前綴進行索引列值的最左邊n 個字符),應用column_list 說明符表示該列的語法為col_name(n) 而不用c o l _ name。例如,下面第一條語句創建了一個具有兩個CHAR 列的表和一個由這兩列組成的索引。第二條語句類似,但只對每個列的前綴進行索引:

在某些情況下,可能會發現必須對列的前綴進行索引。例如,索引行的長度有一個最大上限,因此,如果索引列的長度超過了這個上限,那麼就可能需要利用前綴進 行索引。在MyISAM 表索引中,對BLOB 或TEXT 列也需要前綴索引。對一個列的前綴進行索引限制了以後對該列的更改;不能在不刪除該索引並使用較短前綴的情況下,將該列縮短為一個長度小於索引所用前綴的 長度的列。

3. 刪除索引

可利用DROP INDEX 或ALTER TABLE 語句來刪除索引。類似於CREATE INDEX 語句,DROP INDEX 通常在內部作為一條ALTER TABLE 語句處理,並且DROP INDEX 是在MySQL3.22 中引入的。刪除索引語句的語法如下:

前兩條語句是等價的。第三條語句只在刪除PRIMARY KEY 索引時使用;在此情形中,不需要索引名,因為一個表只可能具有一個這樣的索引。如果沒有明確地創建作為PRIMARY KEY 的索引,但該表具有一個或多個UNIQUE 索引,則MySQL將刪除這些UNIQUE 索引中的第一個。

如果從表中刪除了列,則索引可能會受到影響。如果所刪除的列為索引的組成部分,則該列也會從索引中刪除。如果組成索引的所有列都被刪除,則整個索引將被刪 除。

五.ALTER TABLE 語句

ALTER TABLE 語句是MySQL中一條通用的語句,可用它來做許多事情。我們已經看過了它的幾種功能創建和刪除索引以及將表從一種存儲格式轉換為另一種存儲格式)。本 節中,我們將介紹它的一些其他功能。ALTER TABLE 的完整語法在附錄D 中介紹。

在發現某個表的結構不再反映所希望的東西時, ALTER TABLE很有用處。可能希望用該表記錄其他信息,或者它含有多余的值。或者有的列太小,或者其定義較實際需要來說太大,需要將它們改小以節省存儲空間。 或者發布CREATE TABLE 語句時給出的表名不對。等等,諸如此類的問題,都可以用ALTER TABLE 語句來解決。下面是一些例子:

您正操縱一個基於Web 的問卷,將每份提交的問卷作為表中的一個記錄。後來決定修改此問卷,增加一些問題。這時必須對表增加一些列以存放新問題。

您正在管理一個研究項目。用AUTO_INCREMENT 列分配案例號來研究記錄。您不希望經費延期太長產生多於50 000 個以上的記錄,因此,令該列的類型為UNSIGNED SMALLINT,它能存儲的最大惟一值為65 535。但是,項目的經費延長了,似乎可能另外產生50 000 個記錄。這時,需要使該列的類型更大一些以便存儲更多的件號。

大小的更改也可能是反方向的。可能創建了一個CHAR(255) 列,但現在發現表中沒有比100 個字符更長的串。這時可縮短該列以節省存儲空間。ALTER TABLE 的語法如下:

每個action 表示對表所做的一個修改。MySQL數據庫擴充了ALTER TABLE 語句,允許指定多個動作,各動作間以逗號分隔。這對於減少鍵盤輸入很有用,但這個擴充的更為重要的原因是,除非能同時將所有VARCHAR 列更改為CHAR 列,否則不可能將表從行可變長的表更改為行定長的表。

下面的例子示出了某些ALTER TABLE 的功能。

對表重新命名。這很簡單;只需給出舊表名和新表名即可:

在MySQL3.23 中有臨時表,重命名一個臨時表為數據庫中已經存在的名稱將隱藏原始表,只要臨時表存在就會隱藏原始表。這類似於通過用相同的名字創建一個臨時表來隱藏一個 表的方法。

更改列類型。為了更改列的類型,可使用CHANGE 或MODIFY 子句。假如表my _ t b l中的列為SMALLINT UNSIGNED 的,希望將其更改為MEDIUMINT UNSIGNED 的列。用下面的任何一個命令都可完成此項工作:

為什麼在CHANGE 命令中給出列名兩次?因為CHANGE 可以做的而MODIFY 不能做的一樁事是,除了更改類型外還能更改列名。如果希望在更改類型的同時重新將i 命名為j,可按如下進行:

重要的是命名了希望更改的列,並說明了一個包括列名的列的完整定義。即使不更改列名,也需要在定義中包括相應的列名。

更改列類型的一個重要原因是為了改善比較兩個表的連接查詢的效率。在兩個列的類型相同時,比較更快。假如執行如下的查詢:

如果t1.name 為CHAR( 10 ),而t2.name 為CHAR( 15 ),此查詢的運行速度沒有它們兩者都為CHAR(15) 時的快。那麼可以用下面的任一條命令更改t1.name 使它們的類型相同:

對於3 . 2 3以前的MySQL版本,所連接的列必須是同樣類型的這一點很重要,否則索引不能用於比較。對於版本3.23 或以上的版本,索引可用於不同的類型,但如果類型相同,查詢仍然更快。

將表從可變長行轉換為定長行。假如有一個表chartbl 具有VARCHAR 列,想要把它轉換為CHAR 列,看看能夠得到什麼樣的性能改善。定長行的表一般比變長行的表處理更快。)這個表如下創建:

這裡的問題是需要在相同的ALTER TABLE 語句中一次更改所有的列。不可能一次一列地改完,或者說這個企圖將不起作用。如果執行DESCRIBE chartbl,會發現兩個列仍然是VARCHAR 的列!原因是如果每次更改一列, MySQL注意到表仍然包含有可變長的列,則會把已經更改過的列重新轉換為VARCHAR 以節省空間。為了處理這個問題,應該同時更改所有VARCHAR 列:

現在DESCRIBE 將顯示該表包含的都是CHAR 列。確實,這種類型的操作很重要,因為它使ALTER TABLE 能在相同的語句中支持多個動作。

這裡要注意,在希望轉換這樣的表時:如果表中存在BLOB 或TEXT 列將使轉換表為定長行格式的企圖失敗。即使表中只有一個可變長的列都將會使表有可變長的行,因為這些可變長的列類型沒有定長的等價物。

將表從定長行轉換為可變長的行。雖然, chartbl 用定長行更快,但它要占用更多的空間,因此決定將它轉換回原來的形式以節省空間。這種轉換更為容易。只需將某個CHAR 列轉換為VARCHAR 列,MySQL數據庫就自動地轉換其他的CHAR 列。要想轉換chartbl 表,用下列任一條語句都可以:

轉換表的類型。如果從MySQL3.23 版以前的版本升級到3.23 版或更高,那麼可能會有一些原來創建為ISAM 表的舊表。如果希望使它們為MyISAM 格式,如下操作:

為什麼要這樣做呢?正如在“創建和刪除索引”小節中所介紹的那樣,一個原因是MyISAM 存儲格式具有某些ISAM 格式沒有的索引特性,例如能夠對NULL 值、BLOB 和TEXT 列類型進行索引。另一個原因為, MyISAM 表是獨立於機器的,因此可通過將它們直接拷貝來將它們移到其他機器上,即使那些機器具有不同的硬件體系結構也同樣。這在第11章中將要作進一步的介紹。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved