2016-08-09 68 views
2

Ich habe 3 Tabellen (SuccessOrder, FailedOrder und PendingOrder) mit gleichen Spalten. Jede Tabelle hat mehr als 2 Millionen Datensätze. Ich muss alle Daten aus diesen 3 Tabellen kombinieren und nach CreatedDate sortieren, um sie in meinem Portal anzuzeigen. Ich verwende UNION ALL, um das Ergebnis aller Tabellen zu kombinieren.MySQL Union Performance-Problem

Wenn ich jede Unterabfrage ausführen, erhalten Sie das Ergebnis in 1 oder 2 Sekunden. Wenn ich die gesamte Abfrage (3 Unterabfragen mit UNION ALL) ausführe, dauert es mehr als 5 Minuten.

select * from (
select * from SuccessOrder 
UNION ALL 
select * from FailedOrder 
UNION ALL 
select * from PendingOrder 
) t order by t.ID; 

Gibt es eine Alternative zu UNION ALL?

Ist es möglich, Ansicht von 3 Abfragen ohne UNION ALL zu erstellen?

Im Folgenden werden die von Workbench getesteten Einzel- und Unionsabfragen beschrieben. Ich sehe keinen großen Unterschied zwischen UNION ALL und UNION ALL - ORDER BY

erste Abfrage

Dauer/Fetch Zeit: 2.182 sec/1,513 sec

SELECT col1, col2, ... 
    FROM CompleteTxn ct 
    left outer join CompleteItem ci ON (ct.Id = ci.TxnId) 
    left outer join ItemDispute id ON (ct.Id = id.TxnId and ci.Id = id.ItemId) 
    left outer join Merchant mc ON (ct.MerchantId = mc.Id) 
    left outer join AdditionalTxnInfo addti ON (ct.Id = addti.TxnId) 
    where (ct.PartitionKey>=55 AND ct.PartitionKey<=56) 
     and (ct.TxnCompleteTime >= '2016-08-01 17:00:00' 
     and ct.TxnCompleteTime <= '2016-08-09 17:00:00' 
      ) 
     and ct.MnoId in (22,24,25,23,26,220,221,200,223,224,320, 400) 
     and ct.Status in (1,2,3,4,5); 

Zweite Abfrage

Dauer/Fetch Zeit: 0.279 sec/0,861 sec

SELECT col1, col2, ... 
    FROM FailedOrder ct 
    left outer join FailedItem ci ON (ct.Id = ci.TxnId) 
    left outer join ItemDispute id ON (ct.Id = id.TxnId and ci.Id = id.ItemId) 
    left outer join Merchant mc ON (ct.MerchantId = mc.Id) 
    left outer join AdditionalTxnInfo addti ON (ct.Id = addti.TxnId) 
    where (ct.PartitionKey>=55 AND ct.PartitionKey<=56) 
     and (ct.TxnCompleteTime >= '2016-08-01 17:00:00' 
     and ct.TxnCompleteTime <= '2016-08-09 17:00:00' 
      ) 
     and ct.MnoId in (22,24,25,23,26,220,221,200,223,224,320, 400); 

Union Alle withour Auftrag von

Dauer/Fetch Zeit: 104,802 sec/0,00027 sec

select * 
    FROM 
    (
     SELECT col1, col2, ... 
      FROM FailedOrder ct 
      left outer join FailedItem ci ON (ct.Id = ci.TxnId) 
      left outer join ItemDispute id ON (ct.Id = id.TxnId 
         and ci.Id = id.ItemId 
         ) 
      left outer join Merchant mc ON (ct.MerchantId = mc.Id) 
      left outer join AdditionalTxnInfo addti ON (ct.Id = addti.TxnId) 
    where (ct.PartitionKey>=55 AND ct.PartitionKey<=56) 
     and (ct.TxnCompleteTime >= '2016-08-01 17:00:00' 
     and ct.TxnCompleteTime <= '2016-08-09 17:00:00' 
      ) 
     and ct.MnoId in (22,24,25,23,26,220,221,200,223,224,320, 400) 
       and ct.Status in (1,2,3,4,5) 
    UNION ALL 
     SELECT col1, col2, ... 
      FROM CompleteTxn ct 
      left outer join CompleteItem ci ON (ct.Id = ci.TxnId) 
      left outer join ItemDispute id ON (ct.Id = id.TxnId 
         and ci.Id = id.ItemId 
         ) 
      left outer join Merchant mc ON (ct.MerchantId = mc.Id) 
      left outer join AdditionalTxnInfo addti ON (ct.Id = addti.TxnId) 
    where (ct.PartitionKey>=55 AND ct.PartitionKey<=56) 
     and (ct.TxnCompleteTime >= '2016-08-01 17:00:00' 
     and ct.TxnCompleteTime <= '2016-08-09 17:00:00' 
      ) 
     and ct.MnoId in (22,24,25,23,26,220,221,200,223,224,320, 400)  ) t ; 

Union Alle mit Auftrag von

Dauer/Fetch Zeit: 104,895 sec/0,00028 sec

select * FROM (

SELECT col1, col2, ... FROM FailedOrder ct linker äußerer Join FailedItem ci ON (ct.Id = ci.TxnId) linker äußerer Join ItemDispute ID ON (ct.Id = id.TxnId und ci.Id = id.ItemId) linker äußerer Join Merchant mc ON (ct.MerchantId = mc .Id) linker äußerer Join AdditionalTxnInfo addti ON (ct.Id = addi.TxnId) wo (ct.PartitionKey> = 55 AND ct.PartitionKey < = 56) und (ct.TxnCompleteTime> = '2016-08-01 17:00:00' und ct.TxnCompleteTime < = '2016-08-09 17:00:00') und ct.MnoId in (22,24,25,23,26,220,221,200,223,224,320,400) und ct.Status in (1,2,3,4,5)

UNION ALL

SELECT col1, col2, ... FROM CompleteTxn ct links außen Join CompleteItem ci ON (ct.Id = ci.TxnId) linker äußerer Join ItemDispute id ON (ct.Id = id.TxnId und ci.Id = id.ItemId) linker äußerer Join Händler mc ON (ct.MerchantId = mc.Id) linker äußerer Join AdditionalTxnInfo addti ON (ct.Id = addi.TxnId) wobei (ct.PartitionKey> = 55 UND ct.PartitionKey < = 56) und (ct.TxnCompleteTime> = '2016-08-01 17:00:00' und ct.TxnCompleteTime < = '2016-08-09 17:00:00') und ct.MnoId in (22,24,25,23, 26,220,221,200,223,224,320,400)

) t ORDER BY id desc;

+1

Wenn Sie die 'order by t.ID' entfernen, dann würde es wahrscheinlich viel schneller sein, ansonsten sollte es Zeit brauchen. – 1000111

+0

Warum in aller Welt wollen Sie sechs Millionen Datensätze gleichzeitig abrufen? Das sind drei Table Scans. Indexierung wird hier nicht viel nützen. – e4c5

+0

Wir sammeln nicht gleichzeitig 6 Millionen Datensätze. Wir haben Bedingungen für jede Unterabfrage. Wir müssen die Suche aus diesen 3 Tabellen überprüfen und sie nach ausgewähltem Feld (Mostly ID) ordnen und erste 100 Datensätze für den Benutzer mit Paginierung anzeigen – rkvegiraju

Antwort

0

Nach meiner Annahme haben Sie mit riesigen Daten fast 6 Millionen Datensätze zu tun.

1), wenn Union Vergleich ist Union Alle weitaus schneller

2) Sie alle select-Anweisungen in Abgeleitete Tabelle einnehmen.

3) Wieder tun Sie ORDER BY auf ID (Performance Ausgabe)

Es enorme Auswirkungen auf die Leistung geben wird, wenn Sie auf Huge Daten Auftrag von tun.

das Ergebnis All

select Col1,Col2 from SuccessOrder 
UNION ALL 
select Col1,Col2 from FailedOrder 
UNION ALL 
select Col1,Col2 from PendingOrder 
+0

ernsthaft können Sie bitte diesen einen in Ihrer Frage erstellen @ rkvegiraju – mohan111

+0

Ich führte meine Abfragen in die Workbench und fügte die Dauer jeder Abfrage in der Beschreibung hinzu. sehe nicht viel Unterschied zwischen ** UNION ALL ** und ** UNION ALL - ORDER BY ** – rkvegiraju

0

Ihre order by sind höchstwahrscheinlich die Täter hier erhöht wird SORTIERANLAGEN Kostenanteil so auf jeden Fall in sequentieller Weise bestellt werden erhalten. Sie ordnen im Wesentlichen Ihre gesamte Datenbank nach der Auswahl an, und abhängig davon, wie sie indexiert wurde, kann dies lange dauern.

Sie könnten:

  • sicherstellen, dass die Tabellen auf indiziert sind, was Sie mit (wichtig) bestellen
  • den Auftrag entfernen alltogether von

Ich glaube nicht, dass die union all Kosten kommt den Kosten für das Sortieren all dieser Daten nahe.

+0

Da die geordneten Spalten zu einer Union gehören, die Duplikate enthalten können, bedeutet das nicht, dass der Index auf dem Primärschlüssel unbrauchbar ist ? Es müsste einen neuen Index geben, der auf der Gewerkschaft aufgebaut ist, was meines Wissens nicht möglich ist. Ist das korrekt? –

0

Ich werde Ignoranz plädieren, warum Gewerkschaft so lange im Vergleich zu den Auserwählten ist, jemand, der viel schlauer ist als ich, wird das bezeugen müssen. Ich wiederholte die Ergebnisse, die Sie mit meiner eigenen Datenbank mit einem ähnlichen Overhead erhalten haben. Nachdem dies gesagt ist, wenn Ihr eine subselect Sortierung aus, können Sie die Indizierung der Tabellen

select * from (
(select * from SuccessOrder order by ID limit 100) 
UNION ALL 
(select * from FailedOrder order by ID limit 100) 
UNION ALL 
(select * from PendingOrder order by ID limit 100) 
) t order by t.ID desc limit 100; 

würde die Vorteile der Indizierung verlieren und das Rück Ihre 100 ohne zu viel Aufwand. Wenn Sie möchten, dass alle 6 Millionen Zeilen paged ... das ist etwas anders, aber ein Straight Up letzten 100 ist sinnvoll, aber das hängt davon ab, wie Ihre id Spalte generiert wird, wenn es die Entsprechung einer Datensatznummer ist, hilft diese Antwort niemand.

+0

LIMIT auf Unterabfrage arbeitete für mich. Ich habe das Ergebnis in 0,53 Sekunden. Ich habe 2 weitere Fälle. 1. Benötigen Sie die Gesamtzahl der Datensätze für die Seitennummerierung 2. Manchmal muss ich die Daten in Excel-Dateien exportieren. Linit wird in diesen Fällen nicht funktionieren. – rkvegiraju

0

Einige dieser Tipps helfen können:

  • Sie brauchen nicht die äußeren SELECT
  • Rückkehr nicht Millionen von Zeilen; Verarbeiten Sie sie in MySQL, und liefern Sie nur diejenigen, die Sie benötigen, oder fassen Sie die benötigten zusammen.
  • Wenn Sie nur die ersten verwenden möchten, siehe documentation on UNION
  • Minimieren Sie die Anzahl der zurückzugebenden Spalten. Die zusätzliche Menge zusätzlicher Spalten ist Teil der Verlangsamung.
  • ändern (ct.PartitionKey>=55 AND ct.PartitionKey<=56) zu ct.PartitionKey IN (55,56) wenn praktische
  • In ct.TxnCompleteTime <= '2016-08-09 17:00:00', <=-< ändern.
  • Haben Sie einen Index mit einem der INs zuerst und TxnCompleteTime Sekunde.
  • Betrachten Sie alle Daten in einer Tabelle.

Bitte geben Sie SHOW CREATE TABLE.