Heim > Fragen und Antworten > Hauptteil
Ich versuche, eine SQL-Abfrage zu optimieren, würde aber gerne wissen, wie man es richtig macht.
SELECT r0_.* FROM ride r0_ use index (ride_booking_id_IDX) LEFT JOIN booking b1_ ON r0_.booking_id = b1_.id LEFT JOIN spot s2_ ON r0_.from_spot_id = s2_.id LEFT JOIN spot s3_ ON r0_.to_spot_id = s3_.id WHERE b1_.start_at <= '2023-04-21' AND b1_.end_at >= '2023-04-20' AND b1_.paid_at IS NOT NULL AND b1_.cancelled_at IS NULL AND ((s2_.zone_id = 1 OR s3_.zone_id = 1)) AND s2_.type = 'parking';
Hier erzwinge ich die Verwendung eines Index (booking_id, from_spot_id, to_spot_id)
, der dazu führt, dass die Abfrage etwa 100 ms benötigt, um innerhalb von 25 Sekunden nach dem nächsten Datum ausgeführt zu werden!
booking
表大约有 200 万行,而 ride
Die Tabelle hat etwa 5 Millionen Zeilen.
Ich kann mir jedoch vorstellen, dass mehr Zeilen mithilfe der erzwungenen Indizierung gescannt werden:
id | Typ auswählen | Tisch | Partition | Typ | Mögliche Schlüssel | Schlüssel | key_len | Referenz | OK | Gefiltert | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | Einfach | b1_ | Umfang | Main, booking_id_end_IDX, booking_id_IDX, booking_id_start_IDX, IDX_E00CEDDEB75363F7, IDX_E00CEDDE37D3107C, IDX_E00CEDDEDEA4208C, booking_paid_at_IDX, booking_cancelled_at_IDX | IDX_E00CEDDE37D3107C | 6 | 111456 | 6.6 | Indexbedingungen verwenden; Standorte verwenden | ||
1 | Einfach | r0_ | Referenz | ride_booking_id_IDX | ride_booking_id_IDX | 109 | ector.b1_.id | 1 | 100,0 | ||
1 | Einfach | s2_ | eq_ref | Haupt, IDX_B9327A739F2C3FAB, spot_type_IDX | Haupt | 4 | ector.r0_.from_spot_id | 1 | 72,52 | Verwendungsort | |
1 | Einfach | s3_ | eq_ref | Haupt | Haupt | 4 | ector.r0_.to_spot_id | 1 | 100,0 | Verwendungsort |
Im Vergleich zur gleichen Abfrage ohne Index:
id | Typ auswählen | Tisch | Partition | Typ | Mögliche Schlüssel | Schlüssel | key_len | Referenz | OK | Gefiltert | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | Einfach | s2_ | Referenz | Haupt, IDX_B9327A739F2C3FAB, spot_type_IDX | spot_type_IDX | 767 | Konstant | 161 | 100,0 | Indexbedingungen verwenden | |
1 | Einfach | r0_ | Referenz | IDX_9B3D7CD0ABAF30D3, IDX_9B3D7CD03301C60, ride_booking_id_IDX, booking_from_spot_to_spot_IDX | IDX_9B3D7CD0ABAF30D3 | 5 | ector.s2_.id | 392 | 100,0 | ||
1 | Einfach | b1_ | eq_ref | Main, booking_id_end_IDX, booking_id_IDX, booking_id_start_IDX, IDX_E00CEDDEB75363F7, IDX_E00CEDDE37D3107C, IDX_E00CEDDEDEA4208C, booking_paid_at_IDX, booking_cancelled_at_IDX | Haupt | 108 | ector.r0_.booking_id | 1 | 5.0 | Verwendungsort | |
1 | Einfach | s3_ | eq_ref | Haupt | Haupt | 4 | ector.r0_.to_spot_id | 1 | 100,0 | Verwendungsort |
Soweit ich das beurteilen kann, ist das Datum, mit dem ich vergleiche, der Grund dafür, dass die Abfrage spürbar schneller ist. start_at
和 end_at
从预订 b 中选择 *,其中 b.start_at < '2021-01-01' 和 b.end_at > '2021-01-01';
Sie sorgen dafür, dass diese Abfrage schneller ausgeführt wird, je näher Sie dem Maximal- und Minimalwert kommen (da der Index die meisten Zeilen filtert, sind nur noch sehr wenige Zeilen übrig). (start_at)
和 (end_at)
Typ auswählen | Tisch | Partition | Typ | Mögliche Schlüssel | Schlüssel | key_len | Referenz | OK | Gefiltert | Extra | |
---|---|---|---|---|---|---|---|---|---|---|---|
Einfach | b | Umfang | IDX_E00CEDDEB75363F7,IDX_E00CEDDE37D3107C | IDX_E00CEDDEB75363F7 | 6 | 1147319 | 50 | Indexbedingungen verwenden; Standorte verwenden |