2017-08-30 3 views
1

Ma requête est exécutée trop longtemps. Quand je le profile, je vois quelque chose comme ça:MySQL multiples envoi de données indique

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 

Il y a trop de données d'envoi dedans.

Recherche J'ai couru:

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' 

    ) 

EXPLAIN

 

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 

structures de table MySQL:

 
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

vous manquez certains indices, comme '' OrderID' et tpb' dans la tablette 'OrdersArchive'. La table 'custom_fields' sera toujours très inefficace. Quoi qu'il en soit, je suppose que vous voulez que votre requête s'exécute plus vite, combien plus vite? N'oubliez pas que la plate-forme sur laquelle vous exécutez la requête affecte également la vitesse. –

+0

Les index ajoutés que vous avez mentionnés, stiil mauvais résultats comme interroger 2 minutes. La suppression de la sous-requête à partir de la requête accélère réellement la performance à près de 0,1 s –

+1

La sous-requête renvoie un seul résultat, il n'est donc pas nécessaire d'être une sous-requête. Je ne m'attends pas à ce que MySQL l'exécute pour chaque ligne de OrdersArchive, mais cela pourrait l'être. Puisque vous utilisez PHP, essayez d'abord de faire la sous-requête, puis générez le 'OR ID IN (.....)' avec PHP, donc ce sera un tableau constant d'ID. Combien de factures pourrait-il y avoir? –

Répondre

0

Bien que la requête en cours SELECT pourrait probablement être améliorée dans une certaine mesure, je pense que aiderait beaucoup plus si vous pouviez stocker les données d'une manière plus efficace, surtout si vous pouvez supprimer t il besoin de

ET value comme « % 17.000.106.864% »

Si vous créez un champ distinct pour INVOICENUMBER et le remplir lors de l'insertion de vos données vous pourriez avoir indexé et sélectionnez/join comme ceci:

O invoice invoiceNumber = 17000106864

Si vous recherchez uniquement un enregistrement, l'ajout d'une LIMITE à la requête vous sera également utile.

0

Eh bien, j'accompli cela avec INNER JOIN. Runs 0,34 sec

requête finale est:

 
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

Retour à la question implicite dans le titre ("L'envoi de plusieurs états de données") ...

IN(SELECT ...) est souvent très inefficace. Dans votre cas, il est exécuté de façon répétée, ce qui «exécute» et «envoie des données» pour chaque invocation.

Les autres réponses permettent d'adresser l'autre question implicite ("query runs too long") en transformant cette construction en JOIN.

Autres questions;

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

Vous êtes probablement en proie à des problèmes de performance, dont le schéma est « EAV » (Entité-attribute-value) et vous avez besoin de filtrer en fonction de la valeur une clé (« INVOICENUMBER »). Pensez à le retirer de la table de valeurs-clés (custom_fields) et placez-le dans la table principale (OrdersArchive).

Mais je vois que OrdersArchive a un assez grand nombre de colonnes. Mais je n'ai aucune suggestion concrète à ce sujet.

custom_fields est tout à fait dépourvu d'indices. Voir my tips sur l'indexation d'une table de valeurs-clés commune.