2015-09-05 2 views
1

J'ai deux tables (NewProducts et OldProducts) qui sont comparées. NewProducts a environ 68 000 enregistrements et OldProducts environ 51 000. J'utilise un index couvrant sur chaque table, cependant la requête prend 20 minutes à exécuter, donc je ne l'utilise pas correctement. Est-ce qu'un index de couverture s'applique vraiment avec plusieurs tables? Qu'est-ce que je fais mal? Je vous remercie.Covering Index et deux tables dans mysql

Voici mon code de requête et les index:

$querystring = "SELECT newProducts.Id, newProducts.SKU, 
    newProducts.Title, oldProducts.Title, oldProducts.product_Id 
     FROM 
    newProducts, oldProducts 
     WHERE 
    trim(newProducts.SKU)=trim(oldProducts.SKU) and 
    trim(newProducts.Title)=trim(oldProducts.Title) and 
    oldProducts.Position=1 and 
    oldProducts.Customer=$shop"; 


Indexes for NewProducts: 
Primary: Id 
Index: SKU, Title, customer (not unique) 

Indexes for OldProducts: 
Primary: Id 
Index: Product_id (not unique) 
Index: SKU, Title, Postition, Customer (not unique) 

?> 

CREATE TABLE `NewProducts` (
`Id` bigint(11) NOT NULL, 
`Title` varchar(120) COLLATE utf8_unicode_ci NOT NULL, 
`Category` varchar(100) COLLATE utf8_unicode_ci NOT NULL, 
`Office` varchar(150) COLLATE utf8_unicode_ci NOT NULL, 
`Rehashed` smallint(6) NOT NULL, 
`Quantity` smallint(6) NOT NULL, 
`Price1` decimal(7,2) NOT NULL, 
`Price2` decimal(7,2) NOT NULL, 
`Price3` decimal(7,2) NOT NULL, 
`Price4` decimal(7,2) NOT NULL, 
`created_at` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL, 
`OldQuantity` int(11) NOT NULL, 
`SKU` varchar(55) COLLATE utf8_unicode_ci DEFAULT NULL, 
`Source` varchar(12) COLLATE utf8_unicode_ci NOT NULL, 
`customer` varchar(70) COLLATE utf8_unicode_ci NOT NULL, 
PRIMARY KEY (`Id`), 
UNIQUE KEY `I-T-S` (`ItemId`,`Title`,`SKU`), 
KEY `customer` (`customer`), 
KEY `Title` (`Title`,`Rehashed`), 
KEY `SKU` (`SKU`), 
KEY `Title_2` (`Title`,`SKU`,`customer`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

CREATE TABLE `OldProducts` (
`barcode` varchar(55) COLLATE utf8_unicode_ci DEFAULT NULL, 
`compare_at_price` decimal(10,2) DEFAULT NULL, 
`created_at` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL, 
`fulfillment` varchar(35) COLLATE utf8_unicode_ci DEFAULT NULL, 
`grams` decimal(10,2) DEFAULT NULL, 
`id` bigint(11) NOT NULL, 
`management` varchar(55) COLLATE utf8_unicode_ci DEFAULT NULL, 
`policy` varchar(55) COLLATE utf8_unicode_ci DEFAULT NULL, 
`size` varchar(55) COLLATE utf8_unicode_ci DEFAULT NULL, 
`color` varchar(55) COLLATE utf8_unicode_ci DEFAULT NULL, 
`type` varchar(55) COLLATE utf8_unicode_ci DEFAULT NULL, 
`position` int(11) DEFAULT NULL, 
`price` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL, 
`product_id` bigint(11) NOT NULL, 
`SKU` varchar(55) COLLATE utf8_unicode_ci DEFAULT NULL, 
`Title` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL, 
`quantity` int(11) DEFAULT NULL, 
`customer` varchar(70) COLLATE utf8_unicode_ci NOT NULL, 
PRIMARY KEY (`id`), 
UNIQUE KEY `P-S-T-PO-CUST`  
(`product_id`,`SKU`,`Title`,`position`,`customer`), 
KEY `product_id` (`product_id`), 
+0

Qu'est-ce que SKU? Je ne comprends pas ce champ –

+0

unité de gestion de stock – user3314053

+0

Vous devez présenter vos schémas de table existants, et les 'CREATEd INDEXes', peut-être même afficher un extrait de contenu. Utilisez également 'EXPLAIN' pour révéler le plan de requête. Il semble que vous devriez nettoyer les ID stockés et utiliser un vrai JOIN au lieu du mappage de la clause WHERE. (Bien que nos «personnes» SQL puissent souvent déduire de telles choses, il est plus utile aux futurs utilisateurs si vous incluez autant de détails que possible.) – mario

Répondre

1

TRIM est le méchant. Lorsque vous masquez une colonne indexée (par exemple, SKU) dans une fonction (par exemple, TRIM), l'index ne peut pas être utilisé.

Nettoyer vos données:

  1. corriger le code d'insertion TRIM avant d'insérer (ou insère).
  2. UPDATE tbl SET SKU = TRIM(SKU), title = TRIM(title); - pour chaque table
  3. Modifier le SELECT: TRIM(SKU) ->SKU etc.

encore mieux

oldProducts devrait avoir, dans cet ordre,

`INDEX(`position`,`customer` ,`SKU`,`Title`, `product_id`) 

Avec cela, le WHERE besoin de regarder seulement old lignes pour position=1 and customer =.... (En fait, les 2 premières colonnes peuvent être dans n'importe quel ordre, les 3 dernières dans n'importe quel ordre.)

+0

Affichage des lignes 0 - 29 (47977 au total, Requête a pris 0,0020 sec). Fils d'une arme à feu .... bien c'est un peu plus rapide. Merci monsieur, trim était en effet le problème. – user3314053

+0

Je l'ai fait encore plus vite; voir modifier. –

+0

Merci. Tu es mon héros. :) – user3314053