1. 程式人生 > 其它 >MySQl的遊標特性簡介

MySQl的遊標特性簡介

  MySQL在伺服器端提供只讀的、單向的遊標,而且只能在儲存過程或者更底層的客戶端API中使用。因為MySQL遊標中指向的物件都是儲存在臨時表中而不是實際查詢到的資料,所以MySQL遊標總是隻讀的。它可以逐行指向查詢結果,然後讓程式做進一步的處理。在一個儲存過程中,可以有多個遊標,也可以在迴圈中“巢狀”地使用遊標。

  MySQL的遊標設計也為粗心的人“準備”了陷阱。因為是使用臨時表實現的,所以它在效率上給開發人員一個錯覺。需要記住的最重要的一點是:當你開啟一個遊標的時候需要執行整個査詢。考慮下面的儲存過程:

1  CREATE PROCEDURE bad_cursor()
2  BEGIN
3 DECLARE film_id INT; 4 DECLARE f CURSOR FOR SELECT film_id FROM sakila.film; 5 OPEN f; 6 FETCH f INTO film_id; 7 CLOSE f; 8 END

  從這個例子中可以看到,不用處理完所有的資料就可以立刻關閉遊標。使用Oracle或 者SQL Server的使用者不會認為這個儲存過程有什麼問題,但是在MySQL中,這會帶來很多的不必要的額外操作。使用SHOW STATUS來診斷這個儲存過程,可以看到它需要做1000個索引頁的讀取,做1000個寫入。這是因為在表sakila.film中有1000條記錄,而所有這些讀和寫都發生在第五行的開啟遊標動作。

  這個案例告訴我們,如果在關閉遊標的時候你只是掃描一個大結果集的一小部分,那麼儲存過程可能不僅沒有減少開銷,相反帶來了大量的額外開銷。這時,你需要考慮使用LIMIT來限制返回的結果集。

  遊標也會讓MySQL執行一些額外的I/O操作,而這些操作的效率可能非常低。因為臨時記憶體表不支援BLOB和TEXT型別,如果遊標返回的結果包含這樣的列的話,MySQL就必須建立臨時磁碟表來存放,這樣效能可能會很糟。即使沒有這樣的列,當臨時表大於tmp_table_size的時候,MySQL也還是會在磁碟上建立臨時表。

  MySQL不支援客戶端的遊標,不過客戶端API可以通過快取全部查詢結果的方式模擬客戶端的遊標。這和直接將結果放在一個記憶體陣列中來維護並沒有什麼不同。

作者:小家電維修

相見有時,後會無期。