簡體   English   中英

如何使用Union優化Mysql Select查詢?

[英]How to optimize Mysql Select Query with Union?

我正在使用InnoDb存儲引擎處理mysql數據庫。 我的表結構如下:

表名稱:archiveincomingsms

在此處輸入圖片說明

的索引詳細信息:archiveincomingsms

在此處輸入圖片說明

表名稱:archiveoutgoingsms 在此處輸入圖片說明

的索引詳細信息:archiveoutgoingsms 在此處輸入圖片說明

以上是我的表結構及其索引詳細信息!

兩個表的最小記錄分別超過10億條。

現在的問題是,當我想執行以下SqlQuery時:

      ( SELECT  id AS ID, `recieved_datetime` `Date`, 'MT' AS Type, src_adress AS Msisdn,
               TEXT as text, CHAR_LENGTH(TEXT) AS QtyOfSymbols, 'OK' AS `Status`
            FROM  archiveincomingsms
            WHERE  1=1
              AND  recieved_datetime BETWEEN '2015-06-14 00:00:00'
                                         AND '2015-07-14 23:59:59'
      )
    UNION  ALL
      ( SELECT  id AS ID, `send_date` `Date`, 'MO' AS Type, scr_adress AS Msisdn,
                TEXT as text, CHAR_LENGTH(TEXT) AS QtyOfSymbols, 'OK' AS `Status`
            FROM  archiveoutgoingsms
            WHERE  1=1
              AND  send_date BETWEEN '2015-06-14 00:00:00'
                                 AND '2015-07-14 23:59:59'
      )
    ORDER BY  `Date` ASC
    LIMIT  0 ,100 

以上查詢需要30秒鍾以上的時間才能從表中獲取數據。 還有一個是我也必須為分頁目的計算行數,這還需要30秒鍾以上的時間。

總體而言,執行需要超過1分鍾的時間。 有什么合適的方法可以優化時間嗎? 我必須記下最多5秒。 怎么可能呢? 我正在使用mysql數據庫!

我看不到索引。

請查詢結果:

EXPLAIN (SELECT id AS ID,`recieved_datetime` `Date`,'MT' AS Type,src_adress AS Msisdn,TEXT as text,CHAR_LENGTH(TEXT) AS QtyOfSymbols,'OK' AS `Status` FROM archiveincomingsms
                  WHERE 1=1 AND recieved_datetime BETWEEN '2015-06-14 00:00:00' AND '2015-07-14 23:59:59')
                  UNION ALL
                  (SELECT id AS ID,`send_date` `Date`,'MO' AS Type,scr_adress AS Msisdn,TEXT as text,CHAR_LENGTH(TEXT) AS QtyOfSymbols,'OK' AS `Status` FROM archiveoutgoingsms
                  WHERE 1=1 AND send_date BETWEEN '2015-06-14 00:00:00' AND '2015-07-14 23:59:59') ORDER BY `Date` ASC LIMIT 0 ,100

什么時候使用

ORDER BY `id` ASC

插入

ORDER BY `Date` ASC

在此處輸入圖片說明 這是此查詢說明的結果!

圖片可以通過在新標簽頁中打開來查看! 這里太小了!

MySQL不知道在UNION的第一部分中不使用索引recieved_datetime

您可以告訴MYSQL強制使用索引

查詢1:

EXPLAIN (SELECT id AS ID,`recieved_datetime` `Date`,'MT' AS Type,src_adress AS Msisdn,TEXT as text,CHAR_LENGTH(TEXT) AS QtyOfSymbols,'OK' AS `Status` FROM archiveincomingsms FORCE INDEX(recieved_datetime)
              WHERE 1=1 AND recieved_datetime BETWEEN '2015-06-14 00:00:00' AND '2015-07-14 23:59:59')
              UNION ALL
              (SELECT id AS ID,`send_date` `Date`,'MO' AS Type,scr_adress AS Msisdn,TEXT as text,CHAR_LENGTH(TEXT) AS QtyOfSymbols,'OK' AS `Status` FROM archiveoutgoingsms
              WHERE 1=1 AND send_date BETWEEN '2015-06-14 00:00:00' AND '2015-07-14 23:59:59') ORDER BY `Date` ASC LIMIT 0 ,100

查詢2:

(SELECT id AS ID,`recieved_datetime` `Date`,'MT' AS Type,src_adress AS Msisdn,TEXT as text,CHAR_LENGTH(TEXT) AS QtyOfSymbols,'OK' AS `Status` FROM archiveincomingsms FORCE INDEX(recieved_datetime)
              WHERE 1=1 AND recieved_datetime BETWEEN '2015-06-14 00:00:00' AND '2015-07-14 23:59:59')
              UNION ALL
              (SELECT id AS ID,`send_date` `Date`,'MO' AS Type,scr_adress AS Msisdn,TEXT as text,CHAR_LENGTH(TEXT) AS QtyOfSymbols,'OK' AS `Status` FROM archiveoutgoingsms
              WHERE 1=1 AND send_date BETWEEN '2015-06-14 00:00:00' AND '2015-07-14 23:59:59') ORDER BY `Date` ASC LIMIT 0 ,100

怎么用時間戳代替日期時間2015-06-14 00:00:00

請提供SHOW CREATE TABLE archiveincomingsms; -您所提供的內容更加清晰易讀。 另外,它還顯示引擎和索引。

對於UNION ,您需要

INDEX(send_date),
INDEX(received_date)

但是,由於您要查看一個月的數據量,因此這可能是表格的重要部分。 如果它超過了表的20%,它將進行一次表掃描(或兩次掃描),這意味着UNION並沒有幫助。

旁注:代替

          AND  send_date BETWEEN '2015-06-14 00:00:00'
                             AND '2015-07-14 23:59:59'

這樣會更加干凈和容易:

          AND  send_date >= '2015-06-14'
          AND  send_date <  '2015-06-14' + INTERVAL 1 MONTH

並且會自動處理短短的月份和年份邊界。

表名很難區分。 他們都看起來像

archivemiscellanyms 

哦,我還沒有完成(現在我凝視着表名以查看它們是否不同)...

ORDER BY...LIMIT添加到UNION每個部分:

( SELECT ... ORDER BY received_datetime LIMIT    100 )
UNION ALL
( SELECT ... ORDER BY send_date         LIMIT    100 )
ORDER BY date                           LIMIT 0, 100

如果要“分頁”(彎曲),請在第3頁上執行此操作:

( SELECT ... ORDER BY received_datetime LIMIT      300 )
UNION ALL
( SELECT ... ORDER BY send_date         LIMIT      300 )
ORDER BY date                           LIMIT 200, 100

現在索引將可用。 但是,隨着用戶從一頁到另一頁,它將變得越來越慢。

也許可以加快由“記住你離開的地方”后續頁面。 我的分頁博客 ;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM