2016-07-15 217 views
0

也許是這個星球上最懶惰的MySQL的查詢。我不假裝成爲這個話題的專家 - 我依靠社區來支持。MySQL的優化多個內部連接

我有我需要在查詢運行兩個表。一個表格必須內部連接才能提取鏈接的兩端,然後需要使用第二個表格來提取地理座標。不確定首先要做哪一個。需要一些地理剪裁 - 但這可能是另一天的問題。

過濾應該在頻率場和經度/緯度盒來完成。但最重要的,在同一個表DEVICE_DETAILS的列必須連接在一起,從轉換:

A面,,,,

B面,,,,

TO:

A面,B面,,,,,

加入上的說法應該解釋這更好:

查詢是:

SELECT T.EFL_SYSTEM AS TX_EFL_SYSTEM, 
      T.SITE_ID AS TX_SITE_ID, 
      T.FREQUENCY AS TX_FREQUENCY, 
      T.DEVICE_TYPE AS TX_DEVICE_TYPE, 
      T.EIRP AS TX_EIRP, 
      T.LONGITUDE AS TX_LON, 
      T.LATITUDE AS TX_LAT, 
      R.EFL_SYSTEM AS RX_EFL_SYSTEM, 
      R.SITE_ID AS RX_SITE_ID, 
      R.FREQUENCY AS RX_FREQUENCY, 
      R.DEVICE_TYPE AS RX_DEVICE_TYPE, 
      R.EIRP AS RX_EIRP, 
      ST.LONGITUDE, 
      ST.LATITUDE, 
      SR.LONGITUDE, 
      SR.LATITUDE 
    FROM DEVICE_DETAILS T 
    INNER JOIN DEVICE_DETAILS R ON (T.EFL_SYSTEM=R.EFL_SYSTEM) AND (T.FREQUENCY=R.FREQUENCY) AND (T.DEVICE_TYPE != R.DEVICE_TYPE) 
    INNER JOIN SITE ST ON T.SITE_ID = ST.SITE_ID 
    INNER JOIN SITE SR ON R.SITE_ID = SR.SITE_ID 
    WHERE T.FREQUENCY > 7425000000 AND T.FREQUENCY < 7525000000 AND R.FREQUENCY > 7425000000 AND R.FREQUENCY < 7525000000 AND T.DEVICE_TYPE = 'T'; 

這些是表:

CREATE TABLE `SITE` (
    `SITE_ID` VARCHAR(31) NOT NULL, 
    `LATITUDE` DECIMAL(18,14) NOT NULL, 
    `LONGITUDE` DECIMAL(18,14) NOT NULL, 
    `NAME` VARCHAR(1023) NOT NULL, 
    `STATE` VARCHAR(80) NOT NULL, 
    `LICENSING_AREA_ID` INT(3) NOT NULL, 
    `POSTCODE` VARCHAR(18) NOT NULL, 
    `SITE_PRECISION` VARCHAR(31) NOT NULL, 
    `ELEVATION` INT(5) NOT NULL 
) 
COLLATE='latin1_swedish_ci' 
ENGINE=InnoDB 
; 

對於DEVICE_DETAILS表;錯過了一些領域,但這些是基本的。沒有主鍵可能是因爲我每天早上都做CSV批量導入。我認爲我不得不優化這部分以及在後期階段

+--------------------------------+----------------+------+-----+---------+-------+ 
| Field       | Type   | Null | Key | Default | Extra| 
+--------------------------------+----------------+------+-----+---------+-------+ 
| SDD_ID       | int(10)  | NO |  | NULL || 
| FREQUENCY      | bigint(20)  | NO |  | NULL || 
| BANDWIDTH      | int(15)  | NO |  | NULL || 
| CARRIER_FREQ     | bigint(20)  | NO |  | NULL || 
| EMISSION      | varchar(63) | NO |  | NULL || 
| DEVICE_TYPE     | varchar(1)  | NO |  | NULL || 
| TRANSMITTER_POWER    | int(20)  | NO |  | NULL || 
| SITE_ID      | varchar(31) | NO |  | NULL ||| 
| EFL_SYSTEM      | varchar(63) | NO |  | NULL || 
+--------------------------------+----------------+------+-----+---------+-------+ 

任何反饋或評論在這方面讚賞。

問題:

1 - 這些是多個內部連接好的做法呢?還有什麼其他選項可以優化它 2-我從CSV中使用INFILE輸入(每天);我無法使用源格式。我還可以添加索引嗎?它會影響進口嗎?還有什麼需要優化索引方法? 3-我可以通過指定Long/Lat矩形邊界在SITE表上添加過濾器 - 這是否有助於優化操作?我應該在哪裏我的查詢中添加這些條件

注:我的網站表是圍繞11.5MB和DEVICE_DETAILS約爲232.8 MB。我有8GB的RAM和8個線程處理器。

+0

你能澄清你的具體問題嗎? – mhatch

+0

我的加入方式是否適合我想要實現的目標?這可以優化嗎?目前這個查詢是永久的。 –

+0

您需要允許MySQL充分利用其運行的計算機的資源。這意味着它需要**配置**,因爲它附帶的默認配置可以讓它在真正的舊計算機上工作。你的查詢是永遠的,因爲你沒有爲MySQL做更快的工作。基本上,正確編寫查詢,編制索引以及哪些不是過程的一半。 –

回答

0

你絕對可以通過添加索引到你的表優化。

在這裏閱讀更多:http://dev.mysql.com/doc/refman/5.7/en/mysql-indexes.html

關閉我的頭頂,並沒有看到你的數據(這是很重要的),我會建議添加索引你的主WHERE和JOIN子句:

ALTER TABLE DEVICE_DETAILS ADD INDEX FREQUENCY (FREQUENCY), ADD INDEX DEVICE_TYPE (DEVICE_TYPE), ADD INDEX SITE_ID (SITE_ID); 
ALTER TABLE SITE ADD INDEX SITE_ID (SITE_ID); 

另外,我覺得你可能有一個bug(這不是優化) - 應JOIN到ST有這樣的ON子句:

ON T.SITE_ID = ST.SITE_ID 

相反的:

ON R.SITE_ID = ST.SITE_ID 
+0

我的查詢先按FREQUENCY過濾,然後再進行連接嗎?你也認爲我最好把它分解成多個查詢,這樣mySQL會先解析一個,然後解決另一個問題? –

+0

另外我忘了提及;我使用LOAD DATA LOCAL INFILE從csv文件每天導入數據。我無法控制CSV文件中的列。由於格式不匹配或其他原因,添加索引是否會影響輸入? –

+1

添加索引使這個瘋狂快! 1個查詢的持續時間:0.063秒。感謝您分享您的體驗。 –