sql語句效率
Ⅰ 項目中優化sql語句執行效率的方法是什麼
1. SQL優化的原則是:將一次操作需要讀取的BLOCK數減到最低,即在最短的時間達到最大的數據吞吐量。 調整不良SQL通常可以從以下幾點切入: ? 檢查不良的SQL,考慮其寫法是否還有可優化內容 ? 檢查子查詢 考慮SQL子查詢是否可以用簡單連接的方式進行重新書寫 ? 檢查優化索引的使用 ? 考慮資料庫的優化器 2. 避免出現SELECT * FROM table 語句,要明確查出的欄位。 3. 在一個SQL語句中,如果一個where條件過濾的資料庫記錄越多,定位越准確,則該where條件越應該前移。 4. 查詢時盡可能使用索引覆蓋。即對SELECT的欄位建立復合索引,這樣查詢時只進行索引掃描,不讀取數據塊。 5. 在判斷有無符合條件的記錄時建議不要用SELECT COUNT (*)和select top 1 語句。 6. 使用內層限定原則,在拼寫SQL語句時,將查詢條件分解、分類,並盡量在SQL語句的最里層進行限定,以減少數據的處理量。 7. 應絕對避免在order by子句中使用表達式。 8. 如果需要從關聯表讀數據,關聯的表一般不要超過7個。 9. 小心使用 IN 和 OR,需要注意In集合中的數據量。建議集合中的數據不超過200個。 10. <> 用 < 、 > 代替,>用>=代替,<用<=代替,這樣可以有效的利用索引。 11. 在查詢時盡量減少對多餘數據的讀取包括多餘的列與多餘的行。 12. 對於復合索引要注意,例如在建立復合索引時列的順序是F1,F2,F3,則在where或order by子句中這些欄位出現的順序要與建立索引時的欄位順序一致,且必須包含第一列。只能是F1或F1,F2或F1,F2,F3。否則不會用到該索引。 13. 多表關聯查詢時,寫法必須遵循以下原則,這樣做有利於建立索引,提高查詢效率。格式如下select sum(table1.je) from table1 table1, table2 table2, table3 table3 where (table1的等值條件(=)) and (table1的非等值條件) and (table2與table1的關聯條件) and (table2的等值條件) and (table2的非等值條件) and (table3與table2的關聯條件) and (table3的等值條件) and (table3的非等值條件)。 注:關於多表查詢時from 後面表的出現順序對效率的影響還有待研究。 14. 子查詢問題。對於能用連接方式或者視圖方式實現的功能,不要用子查詢。例如:select name from customer where customer_id in ( select customer_id from order where money>1000)。應該用如下語句代替:select name from customer inner join order on customer.customer_id=order.customer_id where order.money>100。 15. 在WHERE 子句中,避免對列的四則運算,特別是where 條件的左邊,嚴禁使用運算與函數對列進行處理。比如有些地方 substring 可以用like代替。 16. 如果在語句中有not in(in)操作,應考慮用not exists(exists)來重寫,最好的辦法是使用外連接實現。 17. 對一個業務過程的處理,應該使事物的開始與結束之間的時間間隔越短越好,原則上做到資料庫的讀操作在前面完成,資料庫寫操作在後面完成,避免交叉。 18. 請小心不要對過多的列使用列函數和order by,group by等,謹慎使用disti軟體開發t。 19. 用union all 代替 union,資料庫執行union操作,首先先分別執行union兩端的查詢,將其放在臨時表中,然後在對其進行排序,過濾重復的記錄。 當已知的業務邏輯決定query A和query B中不會有重復記錄時,應該用union all代替union,以提高查詢效率。
Ⅱ 如何提高sql語句的執行效率
1、使用ordered提示
Oracle必須花費大量的時間來剖析多表的合並,用以確定表合並的最佳順序。SQL表達式涉及七個乃至更多的表合並,那麼有時就會需要超過30分鍾的時間來剖析,Ordered這個提示(hint)和其他的提示一起使用能夠產生合適的合並順序。
2、使用ordered_predicates
ordered_predicates提示在查詢的WHERE子句里指定的,並被用來指定布爾判斷(Booleanpredicate)被評估的順序。在沒有ordered_predicates的情況下,Oracle會使用下面這些步驟來評估SQL判斷的順序:子查詢的評估先於外層WHERE子句里的Boolean條件。
所有沒有內置函數或者子查詢的布爾條件都按照其在WHERE子句里相反的順序進行評估,即最後一條判斷最先被評估。每個判斷都帶有內置函數的布爾判斷都依據其預計的評估值按遞增排列。
3、限製表格合並評估的數量
提高SQL剖析性能的最後一種方法是強製取代Oracle的一個參數,這個參數控制著在評估一個查詢的時候,基於消耗的優化器所評估的可能合並數量。
(2)sql語句效率擴展閱讀:
1、表設計的優化,數據行的長度不要超過8020位元組,如果超過這個長度的話在物理頁中這條數據會佔用兩行從而造成存儲碎片,降低查詢效率。
2、語句的查詢優化,保證在實現功能的基礎上,盡量減少對資料庫的訪問次數;
3、建立高效的索引創建索引一般有以下兩個目的:維護被索引列的唯一性和提供快速訪問表中數據的策略。
大型資料庫有兩種索引即簇索引和非簇索引,一個沒有簇索引的表是按堆結構存儲數據,所有的數據均添加在表的尾部,而建立了簇索引的表,其數據在物理上會按照簇索引鍵的順序存儲。個表只允許有一個簇索引。
4、強制查詢轉換,有時候oracle 的優化器未必能走正確的查詢路線,這個時候就需要添加一些hint 之類的來規定他的執行路線。當然了,這個未必是最好的處理方案。因為雖然現在走這個路線是對的,以為因為數據的變化到這這個HINT 變得不可取。
Ⅲ 在sql語句多表連接中,in、exists、join哪個效率更高一點
EXISTS、IN與JOIN,都可以用來實現形如「查詢A表中在(或不在)B表中的記錄」的查詢邏輯。
在查詢的兩個表大小相當的情況下,3種查詢方式的執行時間通常是:
EXISTS <= IN <= JOIN
NOT EXISTS <= NOT IN <= LEFT JOIN
只有當表中欄位允許NULL時,NOT IN的方式最慢:
NOT EXISTS <= LEFT JOIN <= NOT IN
但是如果兩個表中一個較小,一個較大,則子查詢表大的用exists,子查詢表小的用in,因為in 是把外表和內表作hash 連接,而exists是對外表作loop循環,每次loop循環再對內表進行查詢。而無論那個表大,用not exists都比not in要快。這是因為如果查詢語句使用了not in 那麼內外表都進行全表掃描,沒有用到索引;而not extsts 的子查詢依然能用到表上的索引。
IN的好處是邏輯直觀簡單(通常是獨立子查詢);缺點是只能判斷單欄位,並且當NOT IN時效率較低,而且NULL會導致不想要的結果。
EXISTS的好處是效率高,可以判斷單欄位和組合欄位,並不受NULL的影響;缺點是邏輯稍微復雜(通常是相關子查詢)。
JOIN用在這種場合,往往是吃力不討好。JOIN的用途是聯接兩個表,而不是判斷一個表的記錄是否在另一個表。
Ⅳ 怎樣提升SQL語句的查詢速度
1.選擇最有效率的表名順序。ORACLE的解析器按照從右到左的順序處理FROM子句中的表名,因此FROM子句中寫在最後的表(基礎表 driving table)將被最先處理. 在FROM子句中包含多個表的情況下,你必須選擇記錄條數最少的表作為基礎表。如果有3個以上的表連接查詢, 那就需要選擇交叉表(intersection table)作為基礎表, 交叉表是指那個被其他表所引用的表。
2.WHERE子句中的連接順序。ORACLE採用自下而上的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他WHERE條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾。
3.SELECT子句中盡量避免使用 『* 』。
4.使用DECODE函數來減少處理時間。
5.查詢結果能不排序就不排序。盡量不用Order by,distinct,union,MINUS,INTERSECT。
6.用表連接代替子查詢in。
7.用索引提高查詢效率。但是索引不能隨便用,還要搞清楚每種索引適用的情況,比如B*索引、復合索引、函數索引、bitmap索引等。雖然使用索引能得到查詢效率的提高,但是也必須注意到它的代價. 索引需要空間來存儲,也需要定期維護, 每當有記錄在表中增減或索引列被修改時, 索引本身也會被修改. 這意味著每條記錄的INSERT , DELETE , UPDATE將為此多付出幾 次的磁碟I/O,因為索引需要額外的存儲空間和處理,那些不必要的索引反而會使查詢反應時間變慢。
8.不能再索引列上適用not、<>、is null、not is null、做四則運算,否則索引會被抑制,不起作用,變成全表掃描。
9.用>=替代>。比如SELECT * FROM S WHERE ID>=4效率SELECT * FROM S WHERE ID>3高。兩者的區別在於, 前者DBMS將直接跳到第一個ID等於4的記錄,而後者將首先定位到ID=3的記錄並且向前掃描到第一個DEPT大於3的記錄。
10.如果表的數據量很大,可以為該表建分區。經常使用的子查詢可以建成視圖。
.
.
.
.
.
.
.
.
Ⅳ MySQL中如何查看「慢查詢」,如何分析執行SQL的效率
一、MySQL資料庫有幾個配置選項可以幫助我們及時捕獲低效SQL語句x0dx0ax0dx0a1,slow_query_logx0dx0a這個參數設置為ON,可以捕獲執行時間超過一定數值的SQL語句。x0dx0ax0dx0a2,long_query_timex0dx0a當SQL語句執行時間超過此數值時,就會被記錄到日誌中,建議設置為1或者更短。x0dx0ax0dx0a3,slow_query_log_filex0dx0a記錄日誌的文件名。x0dx0ax0dx0a4,log_queries_not_using_indexesx0dx0a這個參數設置為ON,可以捕獲到所有未使用索引的SQL語句,盡管這個SQL語句有可能執行得挺快。x0dx0ax0dx0a二、檢測mysql中sql語句的效率的方法x0dx0ax0dx0a1、通過查詢日誌x0dx0a(1)、Windows下開啟MySQL慢查詢x0dx0aMySQL在Windows系統中的配置文件一般是是my.ini找到[mysqld]下面加上x0dx0a代碼如下x0dx0alog-slow-queries = F:/MySQL/log/mysqlslowquery。logx0dx0along_query_time = 2x0dx0ax0dx0a(2)、Linux下啟用MySQL慢查詢x0dx0aMySQL在Windows系統中的配置文件一般是是my.cnf找到[mysqld]下面加上x0dx0a代碼如下x0dx0alog-slow-queries=/data/mysqldata/slowquery。logx0dx0along_query_time=2x0dx0a說明x0dx0alog-slow-queries = F:/MySQL/log/mysqlslowquery。x0dx0a為慢查詢日誌存放的位置,一般這個目錄要有MySQL的運行帳號的可寫許可權,一般都將這個目錄設置為MySQL的數據存放目錄;x0dx0along_query_time=2中的2表示查詢超過兩秒才記錄;x0dx0ax0dx0a2.show processlist 命令x0dx0ax0dx0aSHOW PROCESSLIST顯示哪些線程正在運行。您也可以使用mysqladmin processlist語句得到此信息。x0dx0a各列的含義和用途:x0dx0aID列x0dx0a一個標識,你要kill一個語句的時候很有用,用命令殺掉此查詢 /*/mysqladmin kill 進程號。x0dx0auser列x0dx0a顯示單前用戶,如果不是root,這個命令就只顯示你許可權范圍內的sql語句。x0dx0ahost列x0dx0a顯示這個語句是從哪個ip的哪個埠上發出的。用於追蹤出問題語句的用戶。x0dx0adb列x0dx0a顯示這個進程目前連接的是哪個資料庫。x0dx0acommand列x0dx0a顯示當前連接的執行的命令,一般就是休眠(sleep),查詢(query),連接(connect)。x0dx0atime列x0dx0a此這個狀態持續的時間,單位是秒。x0dx0astate列x0dx0a顯示使用當前連接的sql語句的狀態,很重要的列,後續會有所有的狀態的描述,請注意,state只是語句執行中的某一個狀態,一個 sql語句,以查詢為例,可能需要經過ing to tmp table,Sorting result,Sending data等狀態才可以完成x0dx0ainfo列x0dx0a顯示這個sql語句,因為長度有限,所以長的sql語句就顯示不全,但是一個判斷問題語句的重要依據。x0dx0ax0dx0a這個命令中最關鍵的就是state列,mysql列出的狀態主要有以下幾種:x0dx0aChecking tablex0dx0a正在檢查數據表(這是自動的)。x0dx0aClosing tablesx0dx0a正在將表中修改的數據刷新到磁碟中,同時正在關閉已經用完的表。這是一個很快的操作,如果不是這樣的話,就應該確認磁碟空間是否已經滿了或者磁碟是否正處於重負中。x0dx0aConnect Outx0dx0a復制從伺服器正在連接主伺服器。x0dx0ax0dx0aCopying to tmp table on diskx0dx0a由於臨時結果集大於tmp_table_size,正在將臨時表從內存存儲轉為磁碟存儲以此節省內存。x0dx0aCreating tmp tablex0dx0a正在創建臨時表以存放部分查詢結果。x0dx0adeleting from main tablex0dx0a伺服器正在執行多表刪除中的第一部分,剛刪除第一個表。x0dx0adeleting from reference tablesx0dx0a伺服器正在執行多表刪除中的第二部分,正在刪除其他表的記錄。x0dx0ax0dx0aFlushing tablesx0dx0a正在執行FLUSH TABLES,等待其他線程關閉數據表。x0dx0aKilledx0dx0a發送了一個kill請求給某線程,那麼這個線程將會檢查kill標志位,同時會放棄下一個kill請求。MySQL會在每次的主循環中檢查kill標志位,不過有些情況下該線程可能會過一小段才能死掉。如果該線程程被其他線程鎖住了,那麼kill請求會在鎖釋放時馬上生效。x0dx0aLockedx0dx0a被其他查詢鎖住了。x0dx0aSending datax0dx0a正在處理SELECT查詢的記錄,同時正在把結果發送給客戶端。x0dx0ax0dx0aSorting for groupx0dx0a正在為GROUP BY做排序。x0dx0aSorting for orderx0dx0a正在為ORDER BY做排序。x0dx0aOpening tablesx0dx0a這個過程應該會很快,除非受到其他因素的干擾。例如,在執ALTER TABLE或LOCK TABLE語句行完以前,數據表無法被其他線程打開。正嘗試打開一個表。x0dx0aRemoving plicatesx0dx0a正在執行一個SELECT DISTINCT方式的查詢,但是MySQL無法在前一個階段優化掉那些重復的記錄。因此,MySQL需要再次去掉重復的記錄,然後再把結果發送給客戶端。x0dx0ax0dx0aReopen tablex0dx0a獲得了對一個表的鎖,但是必須在表結構修改之後才能獲得這個鎖。已經釋放鎖,關閉數據表,正嘗試重新打開數據表。x0dx0aRepair by sortingx0dx0a修復指令正在排序以創建索引。x0dx0aRepair with keycachex0dx0a修復指令正在利用索引緩存一個一個地創建新索引。它會比Repair by sorting慢些。x0dx0aSearching rows for updatex0dx0a正在講符合條件的記錄找出來以備更新。它必須在UPDATE要修改相關的記錄之前就完成了。x0dx0aSleepingx0dx0a正在等待客戶端發送新請求.x0dx0ax0dx0aSystem lockx0dx0a正在等待取得一個外部的系統鎖。如果當前沒有運行多個mysqld伺服器同時請求同一個表,那麼可以通過增加--skip-external-locking參數來禁止外部系統鎖。x0dx0aUpgrading lockx0dx0aINSERT DELAYED正在嘗試取得一個鎖表以插入新記錄。x0dx0aUpdatingx0dx0a正在搜索匹配的記錄,並且修改它們。x0dx0ax0dx0aUser Lockx0dx0a正在等待GET_LOCK()。x0dx0aWaiting for tablesx0dx0a該線程得到通知,數據表結構已經被修改了,需要重新打開數據表以取得新的結構。然後,為了能的重新打開數據表,必須等到所有其他線程關閉這個表。以下幾種情況下會產生這個通知:FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE,或OPTIMIZE TABLE。x0dx0awaiting for handler insertx0dx0aINSERT DELAYED已經處理完了所有待處理的插入操作,正在等待新的請求。x0dx0a大部分狀態對應很快的操作,只要有一個線程保持同一個狀態好幾秒鍾,那麼可能是有問題發生了,需要檢查一下。x0dx0a還有其他的狀態沒在上面中列出來,不過它們大部分只是在查看伺服器是否有存在錯誤是才用得著。x0dx0ax0dx0a例如如圖:x0dx0ax0dx0a3、explain來了解SQL執行的狀態x0dx0aexplain顯示了mysql如何使用索引來處理select語句以及連接表。可以幫助選擇更好的索引和寫出更優化的查詢語句。x0dx0a使用方法,在select語句前加上explain就可以了:x0dx0a例如:x0dx0aexplain select surname,first_name form a,b where a.id=b.idx0dx0a結果如圖x0dx0ax0dx0aEXPLAIN列的解釋x0dx0atablex0dx0a顯示這一行的數據是關於哪張表的x0dx0atypex0dx0a這是重要的列,顯示連接使用了何種類型。從最好到最差的連接類型為const、eq_reg、ref、range、indexhe和ALLx0dx0apossible_keysx0dx0a顯示可能應用在這張表中的索引。如果為空,沒有可能的索引。可以為相關的域從WHERE語句中選擇一個合適的語句x0dx0akeyx0dx0a實際使用的索引。如果為NULL,則沒有使用索引。很少的情況下,MYSQL會選擇優化不足的索引。這種情況下,可以在SELECT語句 中使用USE INDEX(indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制MYSQL忽略索引x0dx0akey_lenx0dx0a使用的索引的長度。在不損失精確性的情況下,長度越短越好x0dx0arefx0dx0a顯示索引的哪一列被使用了,如果可能的話,是一個常數x0dx0arowsx0dx0aMYSQL認為必須檢查的用來返回請求數據的行數x0dx0aExtrax0dx0a關於MYSQL如何解析查詢的額外信息。將在表4.3中討論,但這里可以看到的壞的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,結果是檢索會很慢x0dx0ax0dx0aextra列返回的描述的意義x0dx0aDistinctx0dx0a一旦MYSQL找到了與行相聯合匹配的行,就不再搜索了x0dx0aNot existsx0dx0aMYSQL優化了LEFT JOIN,一旦它找到了匹配LEFT JOIN標準的行,就不再搜索了x0dx0aRange checked for each Record(index map:#)x0dx0a沒有找到理想的索引,因此對於從前面表中來的每一個行組合,MYSQL檢查使用哪個索引,並用它來從表中返回行。這是使用索引的最慢的連接之一x0dx0aUsing filesortx0dx0a看到這個的時候,查詢就需要優化了。MYSQL需要進行額外的步驟來發現如何對返回的行排序。它根據連接類型以及存儲排序鍵值和匹配條件的全部行的行指針來排序全部行x0dx0aUsing indexx0dx0a列數據是從僅僅使用了索引中的信息而沒有讀取實際的行動的表返回的,這發生在對表的全部的請求列都是同一個索引的部分的時候x0dx0aUsing temporaryx0dx0a看到這個的時候,查詢需要優化了。這里,MYSQL需要創建一個臨時表來存儲結果,這通常發生在對不同的列集進行ORDER BY上,而不是GROUP BY上x0dx0aWhere usedx0dx0a使用了WHERE從句來限制哪些行將與下一張表匹配或者是返回給用戶。如果不想返回表中的全部行,並且連接類型ALL或index,這就會發生,或者是查詢有問題不同連接類型的解釋(按照效率高低的順序排序)x0dx0aconstx0dx0a表中的一個記錄的最大值能夠匹配這個查詢(索引可以是主鍵或惟一索引)。因為只有一行,這個值實際就是常數,因為MYSQL先讀這個值然後把它當做常數來對待x0dx0aeq_refx0dx0a在連接中,MYSQL在查詢時,從前面的表中,對每一個記錄的聯合都從表中讀取一個記錄,它在查詢使用了索引為主鍵或惟一鍵的全部時使用x0dx0arefx0dx0a這個連接類型只有在查詢使用了不是惟一或主鍵的鍵或者是這些類型的部分(比如,利用最左邊前綴)時發生。對於之前的表的每一個行聯合,全部記錄都將從表中讀出。這個類型嚴重依賴於根據索引匹配的記錄多少—越少越好x0dx0arangex0dx0a這個連接類型使用索引返回一個范圍中的行,比如使用>或<查找東西時發生的情況x0dx0aindexx0dx0a這個連接類型對前面的表中的每一個記錄聯合進行完全掃描(比ALL更好,因為索引一般小於表數據)x0dx0aALLx0dx0a這個連接類型對於前面的每一個記錄聯合進行完全掃描,這一般比較糟糕,應該盡量避免