2011-01-14 4 views
0

Ich schrieb den folgenden UPDATE-Befehl, aber es gibt Redundanz in den Unterauswahlen. Ich bin kein Experte für SQL und würde mich freuen, wenn ich diese Abfrage effizienter machen könnte. Danke im voraus.Mysql Update-Befehl mit mehreren ähnlichen Unterauswahlen

update trips 
    set origin = 
    (select stop_name 
    from stops 
    inner join stop_times 
    on stops.stop_id = stop_times.stop_id 
    where stop_times.trip_id = trips.trip_id 
    order by stop_sequence asc 
    limit 1) 
    , 
    destination = 
    (select stop_name 
    from stops 
    inner join stop_times 
    on stops.stop_id = stop_times.stop_id 
    where stop_times.trip_id = trips.trip_id 
    order by stop_sequence desc 
    limit 1) 
    , 
    starts = 
    (select arrival_time 
    from stop_times 
    where stop_times.trip_id = trips.trip_id 
    order by stop_sequence asc 
    limit 1) 
    , 
    ends = 
    (select arrival_time 
    from stop_times 
    where stop_times.trip_id = trips.trip_id 
    order by stop_sequence desc 
    limit 1) 
; 

Im Folgenden finden Sie die relevanten Tabellendefinitionen. Es gibt ungefähr 72K Reisen, 8K Haltestellen und 2 Millionen Stoppzeiten. Vielleicht ein Durchschnitt von 20? stoppt pro Fahrt (nur Raten).

create table stop_times (
    trip_id varchar(255), 
    arrival_time time, 
    stop_id varchar(255), 
    stop_sequence int unsigned, 
) type=MyISAM; 

alter table stop_times add index stop_id (stop_id(5)); 
alter table stop_times add index trip_id (trip_id(5)); 

create table stops (
    stop_id varchar(255), 
    stop_name varchar(255), 
    stop_lat float, 
    stop_lon float, 
    primary key (stop_id) 
) type=MyISAM; 

create table trips (
    route_id varchar(255), 
    trip_id varchar(255), /* primary key is here */ 
    /* denormalized fields */ 
    origin varchar(255), 
    destination varchar(255), 
    starts time, 
    ends time, 
    primary key(trip_id) 
) type=MyISAM; 
alter table trips add index route_id (route_id(5)); 
+1

Wie haben Sie gemessen, dass es ineffizient ist? –

+1

Bitte geben Sie Ihre Tabellendefinitionen sowie die Anzahl der Haltestellen für jede Reise an. –

+0

Ich habe keine Ahnung, ob es im Vergleich zu einer besseren Lösung ineffizient ist, wenn es eine gibt. Ich führe dies über einen großen Datensatz und es dauert viele Minuten. Was SQL betrifft, sieht es für Sie OK aus? – dan

Antwort

1

zuerst einen Index auf stop_times hinzufügen

ALTER TABLE stop_times ADD PRIMARY KEY(trip_id, stop_sequence) 

Dann die trip_id und die stop_sequence Spalten versuchen, um diesen Update ausgeführt wird:

update trips t JOIN (
    SELECT trip_id, MIN(stop_sequence) minS, MAX(stop_sequence) maxS 
    FROM stop_times 
    GROUP BY trip_id 
) tg ON t.trip_id = tg.trip_id 
JOIN stop_times stFirst ON tg.trip_id = stFirst.trip_id AND stFirst.stop_sequence = tg.minS 
JOIN stop_times stLast ON tg.trip_id = stLast.trip_id AND stLast.stop_sequence = tg.maxS 
JOIN stops stFirstStop ON stFirst.stop_id = stFirstStop.stop_id 
JOIN stops stLastStop ON stLast.stop_id = stLastStop.stop_id 
SET t.origin = stFirstStop.stop_name, 
    t.destination = stLastStop.stop_name, 
    t.starts = stFirst.arrival_time, 
    t.ends = stLast.arrival_time 

Hinweis: trip_id zu einem INT Wechsel wird geben Sie eine bessere Leistung

Auch die Trips-Tabelle sollte die Herkunft_ID und Ziel speichern ation_id, die später mit der Stops-Tabelle verbunden werden kann, um den Namen zu finden, anstatt den Namen in allen Zeilen zu speichern

+0

Ist das JOIN eine innere Verbindung oder eine linke äußere Verbindung? Entschuldigung, wenn das eine Anfängerfrage ist. Kannst du auch ein wenig erklären, warum das schneller geht? – dan

+0

@dan Inner Join –

+0

Ich kann TRIP ID nicht zu INT ändern, da einige der IDs echte Zeichenfolgen sein können. Können Sie eine kurze Erklärung dazu geben, warum neben dem zusätzlichen Index die Verwendung dieser Joins schneller ist als die ursprünglichen 4 Subselects? Vielen Dank. – dan

Verwandte Themen