2016-07-15 12 views
0

Wahrscheinlich ist das die faulste mySQL-Abfrage auf dem Planeten. Ich behaupte nicht, ein Experte zu diesem Thema zu sein - ich bin auf die Unterstützung der Gemeinschaft angewiesen.MySQL optimiert mehrere innere Joins

Ich habe zwei Tabellen, die ich in einer Abfrage ausführen muss. Eine Tabelle muss innerlich mit sich selbst verbunden sein, um zwei Enden der Verknüpfung zu extrahieren, und muss dann die zweite Tabelle verwenden, um die geografischen Koordinaten zu extrahieren. Nicht sicher, welcher zuerst getan werden muss. Ein bisschen Geografie wird benötigt - aber das ist wahrscheinlich eine Frage für einen anderen Tag.

Die Filterung sollte im Feld FREQUENCY und LONG/LAT erfolgen. Aber am wichtigsten ist, Spalten der gleichen Tabelle DEVICE_DETAILS müssen miteinander verbunden werden, von konvertieren:

Seite A ,,,,

Seite B ,,,,

TO:

Seite A , Seite B ,,,,,

kommen auf Anweisung sollte dies besser erklären:

Die Abfrage ist:

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'; 

Dies sind die Tabellen:

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 
; 

Für die DEVICE_DETAILS Tabelle; einige Felder fehlen, aber das sind die grundlegenden. Es gibt keine Primärschlüssel, wahrscheinlich, weil ich jeden Morgen CSV-Massenimport mache. Ich denke, dass ich dieses Teil auch zu einem späteren Zeitpunkt optimieren muss

+--------------------------------+----------------+------+-----+---------+-------+ 
| 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 || 
+--------------------------------+----------------+------+-----+---------+-------+ 

Alle Rückmeldungen oder Kommentare in dieser Hinsicht geschätzt.

Fragen:

1- Sind diese mehrere INNER gute Praxis JOINS? welche anderen Optionen gibt es optimieren Sie es 2- Ich verwende INFILE-Import (täglich) von CSV; und ich kann nicht mit dem Quellformat spielen. Kann ich noch Indizes hinzufügen? Beeinflusst es die Einfuhr? alles andere, um den Indexansatz zu optimieren? 3- Ich kann Filter in der SITE-Tabelle hinzufügen, indem ich die Rechteckgrenze für Long/Lat festlege - hilft das, die Operation zu optimieren? Wo soll ich diese Bedingungen in meiner Abfrage hinzufügen

Hinweis: Meine SITE-Tabelle ist etwa 11,5 MB und DEVICE_DETAILS ist ca. 232,8 MB. Ich habe 8 GB RAM und 8 Threads-Prozessor.

+0

Können Sie Ihr spezifisches Problem/Ihre Frage klären? – mhatch

+0

Ist mein Beitritt Ansatz für das, was ich versuche zu erreichen? Kann das optimiert werden? Derzeit dauert diese Abfrage für immer. –

+0

Sie müssen MySQL erlauben, die Ressourcen des Computers, auf dem es ausgeführt wird, vollständig zu nutzen. Das bedeutet, dass es ** konfiguriert werden muss, da die mitgelieferte Standardkonfiguration dafür sorgt, dass es auf einem wirklich sehr alten Computer funktioniert. Ihre Abfragen dauern ewig, weil Sie nichts dafür getan haben, dass MySQL schneller arbeitet. Grundsätzlich, die Abfrage richtig schreiben, Indizierung und was nicht ist nur die Hälfte des Prozesses. –

Antwort

0

Sie können auf jeden Fall optimieren, indem Sie INDEXES zu Ihren Tabellen hinzufügen.

Lesen Sie mehr hier: http://dev.mysql.com/doc/refman/5.7/en/mysql-indexes.html

Aus der Spitze von meinem Kopf, und ohne Ihre Daten zu sehen (das ist ganz wichtig), würde ich vorschlagen, Indizes für Ihr Haupt hinzuzufügen WHERE und JOIN-Klauseln:

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); 

Außerdem glaube ich, Sie einen Fehler haben kann (das ist nicht für die Optimierung) - sollte ST die JOIN haben diese ON-Klausel:

ON T.SITE_ID = ST.SITE_ID 

Statt:

ON R.SITE_ID = ST.SITE_ID 
+0

Filtert mein Query zuerst nach FREQUENCY und macht dann das JOINING? Denken Sie auch, dass ich es besser in mehrere Abfragen aufteilen sollte, so dass mySQL zuerst einen auflöst und dann den anderen anspricht? –

+0

Auch ich habe vergessen zu erwähnen; Ich importiere die Daten täglich aus CSV-Dateien mit LOAD DATA LOCAL INFILE. Ich kann die Spalten in den CSV-Dateien nicht steuern. Wird das Hinzufügen von Indizes aufgrund von Formatkonflikten oder etwas anderem zum Import führen? –

+1

Hinzufügen der Indizes machte dies verrückt schnell !!! Dauer für 1 Abfrage: 0,063 Sek. Danke, dass Sie Ihre Erfahrungen geteilt haben. –