2016-03-20 10 views
3

Die folgende Abfrage dauert ungefähr 12 Sekunden, um auszuführen. Ich habe versucht, zu optimieren, war aber nicht in der Lage. Die zu verbindende Tabelle ist ziemlich groß (> 8.000.000 Datensätze).Abfrage mit LINKER VERBINDUNG auf große Tabelle wirklich langsam

SELECT 
    p0_.id AS id_0, 
    p0_.ean AS ean_1, 
    p0_.brand AS brand_2, 
    p0_.type AS type_3, 
    p0_.retail_price AS retail_price_4, 
    p0_.target_price AS target_price_5, 
    min(NULLIF(c1_.delivery_price, 0)) AS sclr_6, 
    COALESCE(((p0_.target_price - min(NULLIF(c1_.delivery_price, 0)))/p0_.target_price * -100), 0) AS sclr_7 
FROM product p0_ 
LEFT JOIN crawl c1_ ON (
    c1_.product_ean = p0_.ean AND (
     c1_.crawl_date = p0_.last_crawl_date OR 
     p0_.last_crawl_date IS NULL 
    ) 
    AND c1_.source_id IN (
     SELECT o2_.source_id AS sclr_8 
     FROM organisation_source o2_ 
     WHERE o2_.organisation_id = 5 
    ) 
) 
WHERE p0_.organisation_id = 5 GROUP BY p0_.ean 

ich schon versucht, die Abfrage in einer Menge verschiedener Möglichkeiten zu schreiben, aber leider habe ich keine Leistung zu gewinnen. Wenn ich die Unterabfrage im letzten UND entferne, hilft es auch nicht.

Siehe unten die Ausgabe der EXPLAIN-Anweisung:

+------+--------------+-------+------+---------------------------------------------------+------------------+---------+------------------------+--------+-------------+ 
| id | select_type | table | type | possible_keys          | key    | key_len | ref     | rows | Extra  | 
+------+--------------+-------+------+---------------------------------------------------+------------------+---------+------------------------+--------+-------------+ 
| 1 | PRIMARY  | p0_ | ref | uniqueConstraint,IDX_D34A04AD9E6B1585    | uniqueConstraint | 5  | const     |  69 | Using where | 
| 1 | PRIMARY  | c1_ | ref | IDX_product_ean,IDX_crawl_date     | IDX_product_ean | 62  | admin_pricev-p.p0_.ean | 468459 | Using where | 
| 2 | MATERIALIZED | o2_ | ref | PRIMARY,IDX_DD91A56E9E6B1585,IDX_DD91A56E953C1C61 | PRIMARY   | 4  | const     |  1 | Using index | 
+------+--------------+-------+------+---------------------------------------------------+------------------+---------+------------------------+--------+-------------+ 

unter den TABLE-Anweisungen des Produkts und Crawl-Tabel CREATE Siehe:

CREATE TABLE `product` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `organisation_id` int(11) DEFAULT NULL, 
    `ean` varchar(20) COLLATE utf8_unicode_ci NOT NULL, 
    `brand` varchar(50) COLLATE utf8_unicode_ci NOT NULL, 
    `type` varchar(50) COLLATE utf8_unicode_ci NOT NULL, 
    `retail_price` decimal(10,2) NOT NULL, 
    `target_price` decimal(10,2) NOT NULL, 
    `last_crawl_date` datetime DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `uniqueConstraint` (`organisation_id`,`ean`), 
    KEY `IDX_D34A04AD9E6B1585` (`organisation_id`), 
    KEY `IDX_target_price` (`target_price`), 
    KEY `IDX_ean` (`ean`), 
    KEY `IDX_type` (`type`), 
    KEY `IDX_last_crawl_date` (`last_crawl_date`), 
    CONSTRAINT `FK_D34A04AD9E6B1585` FOREIGN KEY (`organisation_id`) REFERENCES `organisation` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=927 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

CREATE TABLE `crawl` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `source_id` int(11) DEFAULT NULL, 
    `store_id` int(11) DEFAULT NULL, 
    `product_ean` varchar(20) COLLATE utf8_unicode_ci NOT NULL, 
    `crawl_date` datetime NOT NULL, 
    `takeaway_price` decimal(10,2) DEFAULT NULL, 
    `delivery_price` decimal(10,2) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `IDX_B4E9F1C2953C1C61` (`source_id`), 
    KEY `IDX_B4E9F1C2B092A811` (`store_id`), 
    KEY `IDX_product_ean` (`product_ean`), 
    KEY `IDX_takeaway_price` (`takeaway_price`), 
    KEY `IDX_crawl_date` (`crawl_date`), 
    CONSTRAINT `FK_B4E9F1C2953C1C61` FOREIGN KEY (`source_id`) REFERENCES `source` (`id`), 
    CONSTRAINT `FK_B4E9F1C2B092A811` FOREIGN KEY (`store_id`) REFERENCES `store` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=8606874 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

Jeder hat eine Vorstellung davon, wie die Leistung von verbessern diese Abfrage? Danke vielmals! Wenn mehr Informationen benötigt werden, lass es mich wissen!

+0

Was passiert, wenn Sie die 'IN entfernen (SELECT ..)' Teil? Ist das der langsame Teil? Sie könnten das dann in einen anderen JOIN umschreiben. – Rudie

+0

Haben Sie die Indexierung für die Schlüssel durchgeführt, an denen Sie teilnehmen, wie zum Beispiel: c1_.product_ean & p0_.ean columns? –

+0

@Rudie danke für deinen Kommentar, ich habe schon beim ersten manuellen Ausführen dieser Abfrage versucht und die Ergebnisse direkt in diese Abfrage bekommen, aber das hat leider nicht geholfen. –

Antwort

2

können Sie wahrscheinlich die Abfrage vereinfachen:

SELECT . . . 
FROM product p0_ LEFT JOIN 
    crawl c1_ 
    ON c1_.product_ean = p0_.ean AND 
     c1_.crawl_date = p0_.last_crawl_date AND 
     EXISTS (SELECT 1 
       FROM organisation_source o2_ 
       WHERE o2_.organisation_id = 5 AND c1_.source_id = o2_.source_id 
       ) 
WHERE p0_.organisation_id = 5 
GROUP BY p0_.ean; 

Die p0_.last_crawl_date IS NULL ist vermutlich unnötig. A LEFT JOIN behält alle Zeilen in der ersten Tabelle, auch wenn es einen NULL in einem Vergleich gibt. Ihre Logik entspricht alle Zeilen in der zweiten Tabelle (die die anderen Bedingungen erfüllen). Das mag sein, was du willst, aber ich vermute nicht.

In MySQL ist exists manchmal schneller als in, weshalb ich diesen Teil umgeschrieben habe.

Für diese Abfrage können Sie die Verwendung von Indizes beschleunigen: product(organisation_id, ean, last_crawl_date), crawl(product_ean, crawl_date, source_id) und organisation_source(source_id, organisation_id).

+0

ok es scheint, als wäre es wieder zu langsam gewesen! Ich sollte wirklich daran denken, den Chronometer zu sehen, wann immer du da bist :) –

+0

Wow, ich habe es gerade versucht (ohne die zusätzlichen Indizes hinzuzufügen) und es lief in 1,9 Sekunden, das ist großartig! Ich werde überprüfen, ob die Ergebnisse so sind, wie ich es erwarte. Danke vielmals! –

+0

OK du bist ein leben sicherer, ich habe mir in den letzten paar Tagen diese Frage gestellt. Wir haben es jetzt (inkl. Indizes) von +/- 13 Sek. Zurückgebracht. zurück zu einem miesen 280ms :) Großartig! Danke vielmals. –

1

Versuchen mit zusammengesetzten Indizes auf LEFT JOIN s

CREATE TABLE `product` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `organisation_id` int(11) DEFAULT NULL, 
    `ean` varchar(20) COLLATE utf8_unicode_ci NOT NULL, 
    `brand` varchar(50) COLLATE utf8_unicode_ci NOT NULL, 
    `type` varchar(50) COLLATE utf8_unicode_ci NOT NULL, 
    `retail_price` decimal(10,2) NOT NULL, 
    `target_price` decimal(10,2) NOT NULL, 
    `last_crawl_date` datetime DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `uniqueConstraint` (`organisation_id`,`ean`), 
    KEY `IDX_D34A04AD9E6B1585` (`organisation_id`), 
    KEY `IDX_target_price` (`target_price`), 
    KEY `IDX_ean` (`ean`), 
    KEY `IDX_type` (`type`), 
    KEY `IDX_last_crawl_date` (`last_crawl_date`), 
    INDEX `IDX_testing1` (`ean`,`last_crawl_date`), 
    CONSTRAINT `FK_D34A04AD9E6B1585` FOREIGN KEY (`organisation_id`) REFERENCES `organisation` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=927 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

CREATE TABLE `crawl` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `source_id` int(11) DEFAULT NULL, 
    `store_id` int(11) DEFAULT NULL, 
    `product_ean` varchar(20) COLLATE utf8_unicode_ci NOT NULL, 
    `crawl_date` datetime NOT NULL, 
    `takeaway_price` decimal(10,2) DEFAULT NULL, 
    `delivery_price` decimal(10,2) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `IDX_B4E9F1C2953C1C61` (`source_id`), 
    KEY `IDX_B4E9F1C2B092A811` (`store_id`), 
    KEY `IDX_product_ean` (`product_ean`), 
    KEY `IDX_takeaway_price` (`takeaway_price`), 
    KEY `IDX_crawl_date` (`crawl_date`), 
    INDEX `IDX_testing2` (`source_id`,`product_ean`,`crawl_date`), 
    CONSTRAINT `FK_B4E9F1C2953C1C61` FOREIGN KEY (`source_id`) REFERENCES `source` (`id`), 
    CONSTRAINT `FK_B4E9F1C2B092A811` FOREIGN KEY (`store_id`) REFERENCES `store` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=8606874 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 
+0

Danke für deine Antwort! Ich werde es mit Kompositschlüsseln versuchen, wie Gordon schon erwähnte, das ist ein guter Tipp! –

+0

Wenn ich nur wüsste, dass Gordon in der Zwischenzeit geantwortet hat, hätte ich nichts gepostet. Du kannst ihm vertrauen ;) –