最近應用開發的程過中現出了一個小問題,順便記載一下原因和法方--查詢字段
????1、選取最實用的字段屬性
????MySQL可以很好的持支大據數量的取存,但是一般說來,據數庫中的表越小,在它下面行執的查詢也就會越快。因此,在建創表的時候,為了得獲更好的能性,我們可以將表中字段的寬度設得盡可能小。例如,在定義郵政編碼這個字段時,如果將其設置為CHAR(255),然顯給據數庫增加了不必要的空間,甚至應用VARCHAR種這類型也是余多的,因為CHAR(6)以可就很好的成完任務了。樣同的,如果可以的話,我們應當應用MEDIUMINT而不是BIGIN來定義整型字段。
????另外一個進步效率的法方是在可能的情況下,應當盡量把字段設置為NOT NULL,這樣在來將行執查詢的時候,據數庫不用去較比NULL值。
????對于某些本文字段,例如“份省”或者“性別”,我們可以將它們定義為ENUM類型。因為在MySQL中,ENUM類型被作當值數型據數來處置,而值數型據數被處置起來的度速要比本文類型快得多。這樣,我們又可以進步據數庫的能性。
????2、應用連接(JOIN)來取代子查詢(Sub-Queries)
????MySQL從4.1開始持支SQL的子查詢。這個術技可以應用SELECT語句來建創一個單列的查詢結果,然后把這個結果作為濾過條件用在另一個查詢中。例如,我們要將客戶基本息信表中沒有任何訂單的客戶刪掉除,以可就利用子查詢先從售銷息信表中將全部收回訂單的客戶ID出取來,然后將結果傳遞給主查詢,如下所示:
????DELETE FROM customerinfo WHERE CustomerID NOT in (SELECT CustomerID FROM salesinfo )
????應用子查詢可以一次性的成完很多邏輯上要需多個步調才能成完的SQL操縱,同時也可以防止事務或者表鎖死,并且寫起來也很易容。但是,有些情況下,子查詢可以被更有效率的連接(JOIN).. 替換。例如,設假我們要將全部沒有訂單記載的用戶出取來,可以用面下這個查詢成完:
????SELECT * FROM customerinfo WHERE CustomerID NOT in (SELECT CustomerID FROM salesinfo )
????如果應用連接(JOIN).. 來成完這個查詢作工,度速將會快很多。尤其是當salesinfo表中對CustomerID建有引索的話,能性將會更好,查詢如下:
????SELECT * FROM customerinfo LEFT JOIN salesinfoON customerinfo.CustomerID=salesinfo. CustomerID WHERE salesinfo.CustomerID IS NULL
????連接(JOIN).. 之所以更有效率一些,是因為 MySQL不要需在內存中建創臨時表來成完這個邏輯上的要需兩個步調的查詢作工。
????3、應用合聯(UNION)來取代手動建創的臨時表
????MySQL 從 4.0 的本版開始持支 UNION 查詢,它可以把要需應用臨時表的兩條或更多的 SELECT 查詢合并的一個查詢中。在客戶端的查詢會話束結的時候,臨時表會被主動刪除,從而保障據數庫整潔、高效。應用 UNION 來建創查詢的時候,我們只要需用 UNION作為關鍵字把多個 SELECT 語句連接起來以可就了,要注意的是全部 SELECT 語句中的字段目數要想同。面下的例子就演示了一個應用 UNION的查詢。
????SELECT Name, Phone FROM client UNION SELECT Name, BirthDate FROM author
UNION
SELECT Name, Supplier FROM product
????4、事務
????盡管我們可以應用子查詢(Sub-Queries)、連接(JOIN)和合聯(UNION)來建創林林總總的查詢,但不是全部的據數庫操縱都可以只用一條或多數幾條SQL語句以可就成完的。更多的時候是要需用到一系列的語句來成完某種作工。但是在種這情況下,當這個語句塊中的某一條語句行運錯出的時候,整個語句塊的操縱就會變得不確定起來。想設一下,要把某個據數同時插入兩個相干聯的表中,可能會現出這樣的情況:第一個表中勝利更新后,據數庫忽然現出意外狀態,成造第二個表中的操縱沒有成完,這樣,就會成造據數的不完整,甚至會損壞據數庫中的據數。要防止種這情況,就應當應用事務,它的用作是:要么語句塊中每條語句都操縱勝利,要么都失敗。換句話說,就是可以堅持據數庫中據數的一致性和完整性。事物以BEGIN 關鍵字開始,COMMIT關鍵字束結。在這之間的一條SQL操縱失敗,那么,ROLLBACK命令以可就把據數庫恢復到BEGIN開始之前的狀態。
????BEGIN;
????INSERT INTO salesinfo SET CustomerID=14;
????UPDATE inventory SET Quantity=11
????WHERE item='book';
????COMMIT;
????事務的另一個重要用作是當多個用戶同時應用雷同的據數源時,它可以利用鎖定據數庫的法方來為用戶供提一種安全的問訪方法,這樣可以保障用戶的操縱不被其它的用戶所干擾。
????5、鎖定表
????盡管事務是維護據數庫完整性的一個非常好的法方,但卻因為它的獨占性,有時會影響據數庫的能性,尤其是在很大的應用統系中。由于在事務行執的程過中,據數庫將會被鎖定,因此其它的用戶請求只能臨時待等直到該事務束結。如果一個據數庫統系只有多數幾個用戶
????來應用,事務成造的影響不會成為一個太大的問題;但設假有不計其數的用戶同時問訪一個據數庫統系,例如問訪一個電子商務網站,就會生產較比嚴重的應響延遲。
????其實,有些情況下我們可以通過鎖定表的法方來得獲更好的能性。面下的例子就用鎖定表的法方來成完前面一個例子中事務的功能。
????LOCK TABLE inventory WRITE
SELECT Quantity FROM inventory
WHEREItem='book';
...
????UPDATE inventory SET Quantity=11
WHEREItem='book';
UNLOCK TABLES
????這里,我們用一個 SELECT 語句出取初始據數,通過一些算計,用 UPDATE 語句將新值更新到表中。包含有 WRITE 關鍵字的 LOCK TABLE 語句可以保障在 UNLOCK TABLES 命令被行執之前,不會有其它的問訪來對 inventory 停止插入、更新或者刪除的操縱。
????6、應用外鍵
????鎖定表的法方可以維護據數的完整性,但是它卻不能保障據數的關聯性。這個時候我們以可就應用外鍵。例如,外鍵可以保障每一條售銷記載都指向某一個存在的客戶。在這里,外鍵可以把customerinfo 表中的CustomerID映射到salesinfo表中CustomerID,任何一條沒有正當CustomerID的記載都不會被更新或插入到salesinfo中。
????CREATE TABLE customerinfo
(
CustomerID INT NOT NULL ,
PRIMARY KEY ( CustomerID )
) TYPE = INNODB;
CREATE TABLE salesinfo
(
SalesID INT NOT NULL,
CustomerID INT NOT NULL,
PRIMARY KEY(CustomerID, SalesID),
FOREIGN KEY (CustomerID) REFERENCES customerinfo
(CustomerID) ON DELETECASCADE
) TYPE = INNODB;
????注意例子中的參數“ON DELETE CASCADE”。該參數保障當 customerinfo 表中的一條客戶記載被刪除的時候,salesinfo 表中全部與該客戶相干的記載也會被主動刪除。如果要在 MySQL 中應用外鍵,一定要記住在建創表的時候將表的類型定義為事務安全表 InnoDB類型。該類型不是 MySQL 表的默許類型。定義的法方是在 CREATE TABLE 語句中加上 TYPE=INNODB。如例中所示。
????7、應用引索
????引索是進步據數庫能性的經常使用法方,它可以令據數庫服務器以比沒有引索快得多的度速檢索特定的行,尤其是在查詢語句當中包含有MAX(), MIN()和ORDERBY這些命令的時候,能性進步更為顯明。那該對哪些字段建立引索呢?一般說來,引索應建立在那些將用于JOIN, WHERE判斷和ORDER BY排序的字段上。盡量不要對據數庫中某個含有大批復重的值的字段建立引索。對于一個ENUM類型的字段說來,現出大批復重值是很有可能的情況,例如customerinfo中的“province”.. 字段,在這樣的字段上建立引索將不會有什么助幫;相反,還有可能下降據數庫的能性。我們在建創表的時候可以同時建創適合的引索,也可以應用ALTER TABLE或CREATE INDEX在后以建創引索。此外,MySQL
????從本版3.23.23開始持支全文引索和搜索。全文引索在MySQL 中是一個FULLTEXT類型引索,但僅能用于MyISAM 類型的表。對于一個大的據數庫,將據數裝載到一個沒有FULLTEXT引索的表中,然后再應用ALTER TABLE或CREATE INDEX建創引索,將是非??斓?。但如果將據數裝載到一個已經有FULLTEXT引索的表中,行執程過將會非常慢。
????8、優化的查詢語句
????絕大多數情況下,應用引索可以進步查詢的度速,但如果SQL語句應用不當恰的話,引索將沒法揮發它應有的用作。面下是應當注意的幾個方面。首先,最好是在雷同類型的字段間停止較比的操縱。在MySQL 3.23版之前,這甚至是一個必須的條件。例如不能將一個建有引索的INT字段和BIGINT字段停止較比;但是作為特別的情況,在CHAR類型的字段和VARCHAR類型字段的字段巨細雷同的時候,可以將它們停止較比。其次,在建有引索的字段上盡量不要應用函數停止操縱。
????例如,在一個DATE類型的字段上應用YEAE()函數時,將會使引索不能揮發應有的用作。所以,面下的兩個查詢雖然回返的結果一樣,但后者要比前者快得多。
????SELECT * FROM order WHERE YEAR(OrderDate)<2001;
SELECT * FROM order WHERE OrderDate<"
2001-01-01
";
????樣同的形情也會發生在對值數型字段停止算計的時候:
????SELECT * FROM inventory WHERE Amount/7<24;
SELECT * FROM inventory WHERE Amount<24*7;
????下面的兩個查詢也是回返雷同的結果,但前面的查詢將比前面的一個快很多。第三,在搜索符字型字段時,我們有時會應用 LIKE 關鍵字和通配符,種這做法雖然單簡,但卻也是以牲犧統系能性為價代的。例如面下的查詢將會較比表中的每一條記載。
????SELECT * FROM books
WHERE name like "MySQL%"
????但是如果換用面下的查詢,回返的結果一樣,但度速就要快上很多:
????SELECT * FROM books
WHERE name>="MySQL"and name<"MySQM"
????最后,應當注意防止在查詢中讓MySQL停止主動類型轉換,因為轉換程過也會使引索變得不起用作。
?????? 本文并非原創。
文章結束給大家分享下程序員的一些笑話語錄: 一程序員告老還鄉,想安度晚年,于是決定在書法上有所造詣。省略數字……,準備好文房4寶,揮起毛筆在白紙上鄭重的寫下:Hello World
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
