2017-08-30 3 views
1

Meine Abfrage läuft zu lang. Wenn ich es profiliere, sehe ich etwas in der Art:MySQL multiple Daten senden

Sending data 0.039324 
    executing 0.000011 
    Sending data 0.039662 
    executing 0.000012 
    Sending data 0.040380 
    executing 0.000015 
    Sending data 0.035879 
    executing 0.000012 
    Sending data 0.035426 
    executing 0.000012 
    Sending data 0.038107 
    executing 0.000011 
    Sending data 0.035247 
    executing 0.000011 
    Sending data 0.050108 
    executing 0.000014 
    Sending data 0.045458 
    executing 0.000012 
    Sending data 0.034700 
    executing 0.000012 
    Sending data 0.036205 
    executing 0.000012 
    Sending data 0.034602 
    executing 0.000015 
    Sending data 0.034580 
    executing 0.000012 
    Sending data 0.034477 
    executing 0.000010 
    Sending data 0.034382 
    executing 0.000010 
    Sending data 0.034416 
    executing 0.000011 
    Sending data 0.034335 
    executing 0.000010 
    Sending data 0.034474 
    executing 0.000010 
    Sending data 0.034405 
    executing 0.000010 
    Sending data 0.034433 
    executing 0.000011 
    Sending data 0.034544 
    executing 0.000010 
    Sending data 0.034525 
    executing 0.000011 
    Sending data 0.034459 
    executing 0.000010 
    Sending data 0.034766 
    executing 0.000011 
    Sending data 0.034633 
    executing 0.000010 
    Sending data 0.034574 
    executing 0.000011 
    Sending data 0.034607 
    executing 0.000010 
    Sending data 0.034613 
    executing 0.000011 
    Sending data 0.034394 
    executing 0.000010 
    Sending data 0.034606 
    executing 0.000011 
    Sending data 0.034790 
    executing 0.000011 
    Sending data 0.034614 
    executing 0.000011 
    Sending data 0.034497 
    executing 0.000010 
    Sending data 0.034756 
    executing 0.000010 
    Sending data 0.034440 
    executing 0.000010 
    Sending data 0.034414 
    executing 0.000011 
    Sending data 0.034484 
    executing 0.000011 
    Sending data 0.034490 
    executing 0.000011 
    Sending data 0.034672 
    executing 0.000011 
    Sending data 0.034455 
    executing 0.000011 
    Sending data 0.034430 
    executing 0.000011 
    Sending data 0.034509 
    executing 0.000012 
    Sending data 0.034432 
    executing 0.000012 
    Sending data 0.034348 
    executing 0.000011 
    Sending data 0.034378 
    executing 0.000011 
    Sending data 0.034356 
    executing 0.000011 
    Sending data 0.034631 
    end 0.000014 
    query end 0.000007 
    closing tables 0.000010 
    freeing items 0.000025 
    logging slow query 0.000003 
    logging slow query 0.000004 
    cleaning up 0.000004 

Es ist zu viel Sende-Daten drin. Ich

Frage lautete:

SELECT COUNT(*) as count from OrdersArchive where ID>0 and PId IN ('2564') and 
    (
    ID like '17000106864' 
    OR `OrderID` like '17000106864' 
    OR `ID` IN 
    (
     SELECT `transferID` 
     FROM `custom_fields` 
     WHERE `fieldName` = 'invoiceNumber' 
     AND `value` like '%17000106864%' 
    ) 
    OR `tpb` LIKE '17000106864' 

    ) 

Erklären zeigt

 

id select_type table type possible_keys key key_len ref rows Extra 
1 PRIMARY OrdersArchive range PRIMARY,ID_UNIQUE PRIMARY 4 NULL 41609 Using where 
2 DEPENDENT SUBQUERY custom_fields ALL NULL NULL NULL NULL 93141 Using where 

MySQL Tabellenstrukturen:

 
CREATE TABLE IF NOT EXISTS `OrdersArchive` (
    `ID` int(11) NOT NULL, 
    `ids` int(11) NOT NULL DEFAULT '0', 
    `OrderID` varchar(11) NOT NULL DEFAULT '0', 
    `PricePosition` int(11) NOT NULL DEFAULT '0', 
    `Reverse` tinyint(1) DEFAULT NULL, 
    `DataOrder` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `DataFlightTrain` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `Customer` varchar(255) DEFAULT NULL, 
    `PhoneCustomer` varchar(255) DEFAULT NULL, 
    `EmailCustomer` varchar(255) DEFAULT NULL, 
    `Provider` int(11) DEFAULT NULL, 
    `DeliveryTime` timestamp NULL DEFAULT NULL, 
    `Address1` varchar(255) DEFAULT NULL, 
    `Address2` varchar(255) NOT NULL, 
    `Passangers` varchar(1024) DEFAULT NULL, 
    `PassangersPhones` varchar(255) NOT NULL, 
    `PassangersEmailes` varchar(255) NOT NULL, 
    `FlightTrain` varchar(255) DEFAULT NULL, 
    `QuantityPassangers` int(11) DEFAULT '1', 
    `NamePlate` varchar(255) DEFAULT NULL, 
    `PhoneDriver` varchar(255) DEFAULT NULL, 
    `PhoneDriverNeed` tinyint(1) DEFAULT '0', 
    `Status` int(11) DEFAULT NULL, 
    `Operator` int(11) DEFAULT NULL, 
    `userId` int(11) NOT NULL, 
    `usn` varchar(256) NOT NULL, 
    `ArendaNeed` varchar(255) DEFAULT '', 
    `ArendaHour` int(11) DEFAULT NULL, 
    `ArendaMinutes` varchar(255) DEFAULT '', 
    `Cost` double DEFAULT NULL, 
    `Notes` text NOT NULL, 
    `notes2` varchar(256) NOT NULL DEFAULT '', 
    `PId` int(11) NOT NULL DEFAULT '0', 
    `Voucher` varchar(256) NOT NULL, 
    `Invoice` varchar(256) NOT NULL, 
    `Meet` varchar(255) NOT NULL, 
    `Toward` varchar(255) NOT NULL, 
    `techStatus` int(2) NOT NULL DEFAULT '0', 
    `City` varchar(55) NOT NULL, 
    `City2` varchar(55) NOT NULL, 
    `Auto` varchar(30) NOT NULL, 
    `department` varchar(255) NOT NULL DEFAULT '', 
    `nsktime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `tpb` varchar(255) NOT NULL DEFAULT '', 
    `ban_add_races` int(1) NOT NULL DEFAULT '0', 
    `paid` int(10) NOT NULL DEFAULT '0', 
    `taxi` varchar(255) NOT NULL DEFAULT '', 
    `price_client` int(11) DEFAULT NULL, 
    `comission_from_client` int(11) DEFAULT NULL, 
    `primechanie` varchar(1000) DEFAULT NULL, 
    PRIMARY KEY (`ID`), 
    UNIQUE KEY `ID_UNIQUE` (`ID`), 
    KEY `fk_Orders_Users1_idx` (`Operator`), 
    KEY `fk_Orders_Providers1_idx` (`Provider`), 
    KEY `fk_Orders_OrderStatus1_idx` (`Status`), 
    KEY `ids` (`ids`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

## and other table 

CREATE TABLE IF NOT EXISTS `custom_fields` (
    `ID` int(11) NOT NULL AUTO_INCREMENT, 
    `pid` int(11) NOT NULL, 
    `transferID` int(11) NOT NULL, 
    `fieldName` varchar(255) NOT NULL, 
    `value` varchar(1024) NOT NULL, 
    PRIMARY KEY (`ID`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=325452 ; 

+0

Sie fehlen einige Indizes, wie 'OrderID' und' tpb' in der 'OrdersArchive' Tablette. Die 'custom_fields'-Tabelle wird immer ziemlich ineffizient sein. Wie auch immer, ich nehme an, Sie möchten, dass Ihre Abfrage schneller läuft, wie viel schneller? Vergessen Sie nicht, dass die Plattform, auf der Sie die Abfrage ausführen, ebenfalls die Geschwindigkeit beeinflusst. –

+0

Hinzugefügt Indizes, die Sie erwähnt haben, Stiil schlechte Ergebnisse wie Abfragen von 2 Minuten. Durch das Löschen der Unterabfrage aus der Abfrage wird die Leistung auf fast 0,1 Sekunden beschleunigt. –

+1

Die Unterabfrage gibt ein einzelnes Ergebnis zurück und muss daher keine Unterabfrage sein. Ich erwarte nicht, dass MySQL es für jede Zeile von 'OrderArchive' ausführen wird, aber es könnte. Da Sie PHP verwenden, versuchen Sie zuerst, die Unterabfrage durchzuführen, und generieren Sie dann die OR-ID IN (.....) mit PHP, so dass es sich um ein konstantes Array von IDs handelt. Wie viele Rechnungen könnte es geben? –

Antwort

0

Während die aktuelle SELECT-Abfrage wahrscheinlich bis zu einem gewissen Grad verbessert werden könnte, ich denke, es würde viel mehr helfen, wenn Sie die Daten auf eine effizientere Weise speichern könnten, besonders wenn Sie t entfernen können er braucht für

UND value like ‚% 17000106864%‘

Wenn Sie ein eigenes Feld für InvoiceNumber erstellen und füllen, wenn die Daten einfügen Sie könnten es indiziert haben, und wählen Sie/join es wie folgt aus:

WHERE Rechnungsnummer = 17000106864

Wenn Sie nur nach einem Datensatz suchen, würde das Hinzufügen eines LIMIT zur Abfrage auch helfen.

0

Nun, ich habe dies mit INNER JOIN erreicht. Läuft 0,34 sec

letzte Abfrage ist:

 
SELECT COUNT(`OrdersArchive`.ID) as count, `OrdersArchive`.ID 
FROM `OrdersArchive` 
INNER JOIN `custom_fields` on `OrdersArchive`.ID = `custom_fields`.`transferID` 
WHERE `OrdersArchive`.ID>0 
AND `custom_fields`.`fieldName` = 'invoiceNumber' 
AND 
`OrdersArchive`.PId IN ('2564') AND 
(
    `OrdersArchive`.ID LIKE '17000106864' 
    OR `OrdersArchive`.`OrderID` LIKE '17000106864' 
    OR `OrdersArchive`.`tpb` LIKE '17000106864' 
    OR (
`custom_fields`.`value` like '%17000106864%' 
    ) 
) 
0

Zurück zum implizierten Frage im Titel ("multiple Senden von Daten states") ...

IN(SELECT ...) ist oft sehr ineffizient. In Ihrem Fall wird es wiederholt ausgeführt, wodurch für jeden Aufruf "ausgeführt" und "Daten gesendet" werden.

Die anderen Antworten liefern die andere implizite Frage ("Abfrage läuft zu lang"), indem sie dieses Konstrukt in eine JOIN umwandeln.

Andere Probleme;

PRIMARY KEY (`ID`), -- This is UNIQUE and an INDEX 
UNIQUE KEY `ID_UNIQUE` (`ID`), -- totally redundant; DROP it 

Sie sind wahrscheinlich von Performance-Problemen geplagt wird, da das Schema „EAV“ (Entity-Attribut-Wert) ist, und Sie müssen basierend auf einigen Schlüsselwert filtern („InvoiceNumber“). Ziehen Sie es aus der Schlüsselwerttabelle heraus (custom_fields) und legen Sie es in die Haupttabelle (OrdersArchive).

Aber dann sehe ich, dass OrdersArchive eine ziemlich große Anzahl von Spalten hat. Aber ich habe keinen konkreten Vorschlag dazu.

custom_fields ist ziemlich Indizes beraubt. Siehe my tips zum Indizieren einer gemeinsamen Schlüsselwerttabelle.