<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    心的方向

    新的征途......
    posts - 75,comments - 19,trackbacks - 0
    一: 使用Limit參數優化MySQL查詢
    轉自:http://www.tkk7.com/chenpengyi/archive/2006/07/29/60679.html

    我們在做一些查詢的時候總希望能避免數據庫引擎做全表掃描,因為全表掃描時間長,而且其中大部分掃描對客戶端而言是沒有意義的。那么在 MySQL 中有那些方式是可以避免全表掃面的呢?除了我們大家很熟悉的通過使用索引列或分區等方式來進行查詢的優化之外還有那些呢?

    前些天看了一個老外寫的程序,在 MySQL 查詢中使用了很多 Limit 關鍵字,這就讓我很感興趣了,因為在我印象中, Limit 關鍵字似乎更多被使用 MySQL 數據庫的程序員用來做查詢分頁(當然這也是一種很好的查詢優化),那在這里舉個例子,假設我們需要一個分頁的查詢 ,Oracle中一般來說都是用以下 SQL 句子實現:

    SELECT * FROM

    ( SELECT a1.*, rownum rownum_

    FROM testtable a1

    WHERE rownum > 20)

     WHERE rownum_ <= 1000

           這個語句就能查詢到 testtable 表中的 20 1000 記錄,而且還需要嵌套查詢,效率不會太高,看看 MySQL 的實現:

           SELECT * FROM testtable a1 limit 20,980;

           這樣就能返回 testtable 表中的 21 條到( 20 980 =) 1000 條的記錄。

           實現語法確實簡單,但如果要說這里兩個 SQL 語句的效率,那就很難做比較了,因為在 MySQL Limit 選項有多種不同的解釋方式,不同方式下的速度差異是很大的,因此我們不能從這語句的簡潔程度就說誰的效率高。

           不過對程序員來說,夠簡單就好,因為維護成本低,呵呵。

           下面講講這個 Limit 的語法吧:

           SELECT ……. --Select 語句的其他參數

    [LIMIT {[offset,] row_count | row_count OFFSET offset}]

    這里 offset 是偏移量(這個偏移量的起始地址是 0 ,而不是 1 ,這點很容易搞錯的)顧名思義就是離開起始點的位置,而 row-count 也是很簡單的,就是返回的記錄的數量限制。

    Eg. SELECT * FROM testtable a limit 10,20 where ….

    這樣就能使結果返回 10 行以后(包括 10 行自身)的符合 where 條件的 20 條記錄。

    那么如果沒有約束條件就返回 10 29 行的記錄。

           那這跟避免全表掃描有什么關系呢? 下面是 MySQL 手冊對 Limit 參數優化掃描的一些說明:

    在一些情況中,當你使用 LIMIT 選項而不是使用 HAVING 時, MySQL 將以不同方式處理查詢。

    l          如果你用 LIMIT 只選擇其中一部分行,當 MySQL 一般會做完整的表掃描時,但在某些情況下會使用索引(跟 ipart 有關)。

    l          如果你將 LIMIT n ORDER BY 同時使用,在 MySQL 找到了第一個符合條件的記錄后,將結束排序而不是排序整個表。

    l          LIMIT n DISTINCT 同時使用時, MySQL 在找到一個記錄后將停止查詢。

    l          某些情況下, GROUP BY 能通過順序讀取鍵 ( 或在鍵上做排序 ) 來解決,并然后計算摘要直到鍵值改變。在這種情況下, LIMIT n 將不計算任何不必要的 GROUP

    l          MySQL 完成發送第 n 行到客戶端,它將放棄余下的查詢。

    l          LIMIT 0 選項總是快速返回一個空記錄。這對檢查查詢并且得到結果列的列類型是有用的。

    l          臨時表的大小使用 LIMIT # 計算需要多少空間來解決查詢。


    二:在MySQL查詢結果集中得到記錄行號(轉自:http://www.zeali.net/entry/452)

    如果需要在查詢語句返回的列中包含一列表示該條記錄在整個結果集中的行號, ISO SQL:2003 標準提出的方法是提供 ROW_NUMBER() / RANK() 函數。 Oracle 中可以使用標準方法(8i版本以上),也可以使用非標準的 ROWNUM ; MS SQL Server 則在 2005 版本中提供了 ROW_NUMBER() 函數;但在 MySQL 中似乎還沒有這樣的系統自帶功能。雖然 LIMIT 可以很方便的對返回的結果集數量和位置進行過濾,但過濾出來的記錄的行號卻沒辦法被 SELECT 到。據說 MySQL 是早就想增加這個功能了,但我是還沒找到。

    解決方法是通過預定義用戶變量來實現:

    set @mycnt = 0;
    select (@mycnt := @mycnt + 1) as ROWNUM , othercol from tblname order by othercol;

    這樣查詢出來的結果集中 ROWNUM 就保存了行編號信息。這個行編號信息的某種用途在于當你需要根據需要對數據按照某種規則排序并取出排序之后的某一行數據,并且希望知道這行數據在之前排序中的位置時就用得著了。比如:

    set @mycnt = 0;
    select * from (
        select (@mycnt := @mycnt + 1) as ROWNUM , othercol
         from tblname order by othercol
    ) as A where othercol=OneKeyID;

    當然你也可以通過創建臨時表的方法把查詢結果寫到某個擁有 auto_increment 字段的臨時表中再做查詢,但考慮到臨時表在 MySQL master / slave 模式下可能產生的問題,用這樣臨時用戶定義變量的方式來計算查詢結果集每一行對應的行號還是更為簡潔 -- 除非你愿意在 PHP 或其他語言腳本中對返回的整個結果集再作處理。


    posted on 2008-06-02 16:26 阿偉 閱讀(876) 評論(0)  編輯  收藏 所屬分類: DateBase
    主站蜘蛛池模板: 亚洲一本到无码av中文字幕| 永久亚洲成a人片777777| 亚洲精品韩国美女在线| 性xxxxx大片免费视频| 国产A在亚洲线播放| 麻豆精品成人免费国产片| 亚洲精品~无码抽插| 在线看片免费人成视频福利| 亚洲熟妇av一区二区三区漫画| 一个人免费观看日本www视频| 亚洲精品国产福利一二区| yy一级毛片免费视频| 亚洲AV无码成人专区片在线观看 | 亚洲乱码精品久久久久..| 国产免费AV片在线观看播放| 国产亚洲美女精品久久久2020 | 亚洲成a人片在线观看老师| 免费在线观看自拍性爱视频| 亚洲欧洲日产国码高潮αv| 国产一二三四区乱码免费| 亚洲精选在线观看| 一个人免费观看www视频在线| 亚洲狠狠色丁香婷婷综合| 国产成人毛片亚洲精品| 免费黄色电影在线观看| 亚洲一区二区三区国产精品无码| 我要看WWW免费看插插视频| 全部在线播放免费毛片| 国产成人亚洲综合色影视| 可以免费看黄的网站| 黄网站色成年片大免费高清 | 亚洲最大福利视频网站| 丁香花在线观看免费观看| 污污视频免费观看网站| 国产∨亚洲V天堂无码久久久| 中文字幕乱码免费视频| 美女被免费网站在线视频免费| 亚洲香蕉成人AV网站在线观看| 四虎在线成人免费网站| 污视频网站免费观看| 亚洲日韩中文字幕天堂不卡|