2010-02-25 5 views
6

Ich versuche, alle Informationen zu book_sales für einen bestimmten Buchautor aufzulisten. Also habe ich eine Abfrage und es verwendet nicht Index, um Datensätze zu suchen.php & mySQL: Abfrage verwendet keinen Index in der Tabellenverknüpfung

Das Folgende ist meine Tabellen Struktur:

-- Table structure for table `books` 

CREATE TABLE IF NOT EXISTS `books` (
    `book_id` int(11) NOT NULL auto_increment, 
    `author_id` int(11) unsigned NOT NULL, 
    `book_type_id` int(11) NOT NULL, 
    `book_title` varchar(50) NOT NULL, 
    `book_price` smallint(4) NOT NULL, 
    `in_stock` char(1) NOT NULL, 
    PRIMARY KEY (`book_id`), 
    KEY `book_type_id` (`book_type_id`), 
    KEY `author_id` (`author_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

-- Dumping data for table `books` 

INSERT INTO `books` (`book_id`, `author_id`, `book_type_id`, `book_title`, `book_price`, `in_stock`) VALUES 
(1, 1, 1, 'My Book 1', 10, 'y'), 
(2, 2, 1, 'My Book 2', 20, 'n'), 
(3, 1, 2, 'My Book 3', 30, 'y'), 
(4, 3, 3, 'My Book 4', 40, 'y'), 
(5, 4, 2, 'My Book 5', 50, 'n'), 
(6, 1, 1, 'My Book 6', 60, 'y'), 
(7, 5, 3, 'My Book 7', 70, 'n'), 
(8, 6, 2, 'My Book 8', 80, 'n'), 
(9, 7, 1, 'My Book 9', 90, 'y'), 
(10, 8, 3, 'My Book 10', 100, 'n'); 

-- Table structure for table `book_sales` 

CREATE TABLE IF NOT EXISTS `book_sales` (
    `sale_id` int(11) NOT NULL auto_increment, 
    `book_id` int(11) NOT NULL, 
    `sale_amount` decimal(8,2) NOT NULL default '0.00', 
    `time` datetime NOT NULL default '0000-00-00 00:00:00', 
    `price` smallint(8) NOT NULL, 
    PRIMARY KEY (`sale_id`), 
    KEY `book_id` (`book_id`), 
    KEY `price` (`price`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

-- Dumping data for table `book_sales` 

INSERT INTO `book_sales` (`sale_id`, `book_id`, `sale_amount`, `time`, `price`) VALUES 
(1, 1, '10.00', '2010-02-23 10:00:00', 20), 
(2, 1, '20.00', '2010-02-24 11:00:00', 20); 

Meine Suche:

SELECT sale_amount, price 
FROM book_sales 
INNER JOIN books ON book_sales.book_id = books.book_id 
WHERE books.author_id =1 

Ein EXPLAIN auf dem oben, zeigt mir:

id select_type table  type  possible_keys  key  key_len ref  rows  Extra 
1 SIMPLE   books  ref  PRIMARY,author_id author_id 4   const 3  Using index 
1 SIMPLE   book_sales ALL  book_id    NULL  NULL  NULL  2  Using where 

Klar, book_sales verwendet nicht den Schlüssel 'book_id', obwohl ich es habe. Was kann ich tun, damit die Tabelle book_sales den Index verwendet?

Vielen Dank.

Edits basierend auf Vorschläge gemacht (aber das Ergebnis wird sie verwendet Index immer noch nicht):

//Does not use the index in book_sales table 
EXPLAIN SELECT sale_amount, price 
FROM books, book_sales 
FORCE INDEX (book_id) 
WHERE book_sales.book_id = books.book_id 
AND books.author_id =1 

//Does not use the index in book_sales table 
EXPLAIN SELECT sale_amount, price 
FROM book_sales, books 
WHERE books.author_id = 1 
AND book_sales.book_id = books.book_id 

Wie mit nur 2 Reihen der book_sale Tabelle zu zwingen, den Index zu benutzen? Vielen Dank.

Antwort

12

Versuchen Wie Sie in der EXPLAIN sehen "book_id" wird als möglicher Schlüssel aufgeführt. Wenn MySQL es nicht verwendet, ist es nur, dass das Optimierungsprogramm nicht denkt, dass es die Abfrage beschleunigen würde. Das ist richtig, wenn "book_sales" nur 2 Zeilen hat und 100% dieser Zeilen die gleiche "book_id" haben. Es heißt Kardinalität BTW. How to Avoid Table Scans (MySQL Handbuch)

Versuchen Sie es mit mehr Zeilen zu füllen und Sie sollten sehen, dass MySQL einen Index für den Join verwenden wird.

Edit: die Abfrage

SELECT sale_amount, price 
FROM books, book_sales 
FORCE INDEX (book_id) 
WHERE book_sales.book_id = books.book_id 
AND books.author_id =1 

... werden auch nicht in diesem Fall arbeiten, weil der Optimierer immer noch, dass der Index Lesen erkennt suboptimal und schaltet den Tisch, um damit zu vermeiden. Sie können die Tabellenreihenfolge erzwingen, indem Sie STRAIGHT_JOIN verwenden. Dies ist jedoch ein bisschen ein Hack, weil es MySQL zwingt, die Abfrage auf eine Weise auszuführen, die nicht die beste ist.

 EXPLAIN 
     SELECT sale_amount, price 
     FROM books 
STRAIGHT_JOIN book_sales FORCE INDEX (book_id) ON book_sales.book_id = books.book_id 
     WHERE books.author_id = 1 
+2

Genau. In der Regel wird ein Index verlangsamen, wenn Sie mehr als 25% der Tabelle auswählen. –

+0

+1 Das ist in allen Fällen richtig und gültig. – streetparade

+0

@Josh Davis Danke für die Antwort.Wie Sie vorgeschlagen haben, füllte ich die Tabelle mit zusätzlichen Daten und als ich die Abfrage ausprobierte, die ich bei mir hatte, funktionierte es! Die Tabelle book_sales verwendete den Schlüssel book_id !!! Erleichterung endlich !!! Also hier war der Verursacher das MySQL-Abfrageprotokoll langsam. Ich hatte es eingeschaltet und protokollierte alle Abfragen, die keinen Index verwendeten, und diese Abfrage tauchte im Protokoll auf und mein Kampf begann damit. Gibt es irgendeine Möglichkeit, wie ich dieses Protokoll unterdrücken kann, wenn ich die Anfragen der oben genannten Art zeige? Vielen Dank! – Devner

0

dieses

SELECT sale_amount, price 
FROM book_sales,books 
LEFT JOIN books ON(book_sales.book_id = books.book_id) 
WHERE books.author_id =1 
+0

Vielen Dank für die Antwort. Ich habe deinen Code ausprobiert. Habe die "# 1066 - Nicht eindeutige Tabelle/Alias: 'Bücher'" Error. Also habe ich ", Bücher" in der FROM-Klausel entfernt. Hat es erklärt und trotzdem benutzt es den Index nicht. Was können wir noch tun, um das zu beheben? – Devner

+0

Hy Devner Bitte folgen Sie der Antwort von Josh Davis – streetparade

+0

Ich tat, und ich besuchte den Link, den er gepostet. Ich sehe eine Option namens "--max-sucht-for-key = 1000". Dort steht: "Starten Sie mysqld mit der Option --max-seeks-for-key = 1000 oder verwenden Sie SET max_seeks_for_key = 1000, um dem Optimierer mitzuteilen, dass kein Schlüsselscan mehr als 1.000 Schlüsselsuchvorgänge verursacht." Ich bin mir nicht sicher, was das wirklich bedeutet. Kannst du bitte Licht darauf werfen? Vielen Dank. – Devner

Verwandte Themen