2016-08-08 13 views
2

Ich arbeite derzeit an großen Datenbank, die> 1 Million Datensätze enthält, verwende ich die unten Abfrage zu vollen Datensätze auf meine Kriterien basiert, aber es ist zu langsam, obwohl ich den Primärschlüssel indexieren .MySQL Abfrage Optimierung mit where Anweisung

SQL:

SELECT DISTINCT title, productID, catID, description, productUrl, 
    regularPrice, salePrice, imageUrl, merID, created_at, 
    updated_at, name, link, source 
FROM products p, advertisers a 
WHERE (title LIKE '%headphone%' OR description LIKE '%headphone%') 
AND catID=22 
AND regularPrice IS NOT NULL 
AND p.merID = a.advertID 

Kann mir jemand helfen, wie die Abfrage zu optimieren?

Danke,

EDIT:

Tabellenstrukturen:

CREATE TABLE `products` (
    `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    `productID` varchar(50) COLLATE utf8_unicode_ci NOT NULL UNIQUE, 
    `catID` varchar(50) COLLATE utf8_unicode_ci NOT NULL, 
    `title` text COLLATE utf8_unicode_ci, 
    `description` longtext COLLATE utf8_unicode_ci, 
    `productUrl` text COLLATE utf8_unicode_ci NOT NULL, 
    `regularPrice` double(8,2) DEFAULT NULL, 
    `salePrice` double(8,2) NOT NULL, 
    `imageUrl` text COLLATE utf8_unicode_ci NOT NULL, 
    `merID` varchar(50) COLLATE utf8_unicode_ci NOT NULL UNIQUE, 
    `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

CREATE TABLE `advertisers` (
    `id` int(10) UNSIGNED NOT NULL PRIMARY KEY, 
    `advertID` varchar(50) COLLATE utf8_unicode_ci NOT NULL UNIQUE, 
    `name` text COLLATE utf8_unicode_ci NOT NULL, 
    `link` text COLLATE utf8_unicode_ci NOT NULL, 
    `logo` text COLLATE utf8_unicode_ci NOT NULL, 
    `source` varchar(10) COLLATE utf8_unicode_ci NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

ERKLÄREN:

mysql> EXPLAIN EXTENDED SELECT DISTINCT title, productID, catID, description, productUrl, regularPrice, salePrice, imageUrl, merID, created_at, updated_at, name, link, source FROM products p, advertisers a WHERE (title LIKE '%headphone%' OR description LIKE '%headphone%') AND catID=22 AND regularPrice IS NOT NULL AND p.merID = a.advertID; 
+----+-------------+-------+------------+--------+---------------------+----------+---------+-------------------+--------+----------+------------------------------+ 
| id | select_type | table | partitions | type | possible_keys  | key  | key_len | ref    | rows | filtered | Extra      | 
+----+-------------+-------+------------+--------+---------------------+----------+---------+-------------------+--------+----------+------------------------------+ 
| 1 | SIMPLE  | p  | NULL  | ALL | merID    | NULL  | NULL | NULL    | 682242 |  1.89 | Using where; Using temporary | 
| 1 | SIMPLE  | a  | NULL  | eq_ref | advertID,advertID_2 | advertID | 152  | datafeeds.p.merID |  1 | 100.00 | NULL       | 
+----+-------------+-------+------------+--------+---------------------+----------+---------+-------------------+--------+----------+------------------------------+ 
2 rows in set, 2 warnings (0.00 sec) 
+1

anzeigen CREATE TABLE' Abfrage – mnv

+1

Verwenden Sie die 'EXPLAIN' Funktion mysql Angebote. Siehe hierzu die Dokumentation. Es ermöglicht Ihnen, genau zu verstehen, wie mysql in der Lage ist, die Übereinstimmungen auszuwählen, welche Indizes es verwendet und was möglicherweise fehlt. – arkascha

+0

Ich würde empfehlen, keine JOIN-Syntax zu verwenden, die ungefähr zwei Dekaden veraltet ist. Stellen Sie andernfalls sicher, dass die verbundenen Felder (auf beiden Seiten) ebenfalls indiziert sind. – Uueerdo

Antwort

0

Prüfung für den Index in der Verbindungsschlüssel merid für Produkte und advertID für Werbetreibende

SELECT DISTINCT 
    title 
    , productID 
    , catID 
    , description 
    , productUrl 
    , regularPrice 
    , salePrice 
    , imageUrl 
    , merID 
    , created_at 
    , updated_at 
    , name 
    , link 
    , source 
FROM products p 
INNER JOIN advertisers a ON p.merID = a.advertID 
WHERE (title LIKE '%headphone%' OR description LIKE '%headphone%') 
AND catID=22 
AND regularPrice IS NOT NULL 

coulb auf der (wahrscheinlich) nützlich, um einen zusammengesetzten Index sein selektivere Spalten Spalte

(catID, merID) 

regularPrice, Titel und Beschreibung durch die Verwendung von wie und si nicht null Sie sollten nicht in Composite-Index nützlich sein

+0

'Aktuelle Auswahl enthält keine eindeutige Spalte. Gitter bearbeiten, Kontrollkästchen, Bearbeiten, Kopieren und Löschen Funktionen sind nicht verfügbar. Ich bekomme diese Warnung – aliocee

+0

Die Warnung .. wird angezeigt, wenn ?? Was versuchst du zu tun? und was bedeutet "Gitter bearbeiten, Kontrollkästchen, Bearbeiten, Kopieren und Löschen sind nicht verfügbar"? – scaisEdge

0

MySQL unterstützt Volltextindizes für InnoDB-Tabellen seit Version 5.6.

Ich empfehle Ihnen, die Volltextsuche zu verwenden.

ALTER TABLE products 
ADD FULLTEXT (title, description); 

Und ersetzen

WHERE (title LIKE '%headphone%' OR description LIKE '%headphone%') 

Um

WHERE MATCH (title, description) AGAINST ('headphone'); 
+0

erstaunlich! es hat funktioniert – aliocee

+0

Tolle Neuigkeiten! Dennoch empfehle ich dringend, dass Sie etwas über die vorgeschlagene 'EXPLAIN'-Funktion erfahren, um selbst eine Lösung für Indexprobleme finden zu können. – arkascha

+0

Vielen Dank, kann es eine Wildcard-Suche sein? – aliocee