2009-07-17 11 views
7

Mam złożony indeks oparty na 3 kolumnach, z których dwa są ograniczone w moim zapytaniu, a trzeci jest w porządku według klauzuli, ale mysql nie używa indeksu do sortowania.Optymalizowanie mojego zapytania mysql do użycia indeksu do sortowania

 
explain select * from videos where public_private='public' and approved='yes' order by number_of_views desc; 

+----+-------------+--------+------+--------------------------------+------+---------+------+---------+-----------------------------+ 
| id | select_type | table | type | possible_keys     | key | key_len | ref | rows | Extra  | 
+----+-------------+--------+------+--------------------------------+------+---------+------+---------+-----------------------------+ 
| 1 | SIMPLE  | videos | ALL | approved,approved_3,approved_2 | NULL | NULL | NULL | 1476818 | Using where; Using filesort | 
+----+-------------+--------+------+--------------------------------+------+---------+------+---------+-----------------------------+ 

Struktura tabeli jest następująca:

CREATE TABLE `videos` (
    `indexer` int(9) NOT NULL auto_increment, 
    `user_id` int(9) default NULL, 
    `public_private` varchar(24) default NULL, 
    `approved` varchar(24) default NULL, 
    `number_of_views` int(9) default NULL, 
    PRIMARY KEY (`indexer`), 
    KEY `approved` (`approved`,`user_id`), 
    KEY `approved_3` (`approved`,`public_private`,`indexer`), 
    KEY `approved_2` (`approved`,`public_private`,`number_of_views`), 
) ENGINE=MyISAM AUTO_INCREMENT=1969091 DEFAULT CHARSET=utf8 | 

Co należy zrobić, aby zmusić do użycia indeksu do sortowania wyników?

Odpowiedz

13

wierzę, że zapytanie masz prawdopodobnie dopasowywania duży odsetek dane w tabeli. W takich sytuacjach Optymalizator MySQL często wybiera skanowanie tabeli i ignoruje indeksy całkowicie, ponieważ jest to faktycznie szybsze niż pokonanie problemu dodatkowego odczytu całego indeksu i wykorzystanie go do wybrania danych. Tak więc w tym przypadku domyślam się, że public_private='yes' and approved='yes' pasuje do dobrej części twojego stołu. Dlatego, jeśli MySQL pomija indeks z tego powodu, nie jest on również dostępny do sortowania.

Jeśli naprawdę chcesz go użyć indeksu, to rozwiązanie byłoby użyć FORCE INDEX:

select * from videos FORCE INDEX (approved_2) where public_private='public' and approved='yes' order by number_of_views desc; 

Chciałbym jednak przeprowadzić kilka testów aby upewnić się, że to, co dostajesz jest rzeczywiście szybciej niż co wybrał optymalizator MySQL. Najwyraźniej optymalizator does have some issues dokonał selekcji w celu zamówienia, więc możesz zdecydowanie zrobić to zdjęcie i sprawdzić, czy uzyskasz lepszą wydajność.

+0

FORCE INDEX rozwiązało problem. Zapytanie jest teraz wykonywane znacznie szybciej i masz rację co do zapytania pasującego do dużej części bazy danych. –

+0

Dobre rzeczy, cieszę się, że działało. – zombat

-2

Zamówienie ma znaczenie w postaci kluczy złożonych. Zapominam o zasadach, ale spróbuj w innej kolejności.

-2

dodać oddzielny indeks do kolumny number_of_views i sprawdzić, czy działa.

Jeśli klucz jest kombinacją 3 kolumny, użyje tego konkretnego klucza tylko gdy jest za pomocą wszystkie 3 wykonać operację

+0

Nie. Poprawnie: Jeśli klucz jest kombinacją 3 kolumn, użyje tego konkretnego klucza, gdy używa pierwszej kolumny lub kombinacji dwóch pierwszych kolumn lub wszystkich trzech kolumn. –

1

Kolejność ma znaczenie w kluczach złożonych. Jeśli chcesz sortować według tylko number_of_views pomocą approved_2 klucza, Change:

KEY `approved_2` (`approved`,`public_private`,`number_of_views`) 

do:

KEY `approved_2` (`number_of_views`,`approved`,`public_private`) 

kompozytowe klucze w pracy MySQL lewej do prawej. W powyższym przykładzie, klucz uznany za pomocą number_of_views, approved, a public_private implicity tworzy indeksy na:

  • number_of_views
  • number_of_views, approved
  • number_of_views, approved, public_private
+0

To rozwiązanie po prostu pozbawia "MySQL" możliwości filtrowania na pierwszych dwóch polach i sortowania na trzecim. – Quassnoi

+0

Zapytał, dlaczego indeks nie był używany do sortowania. –

+1

Indeks, który sugerujesz, może być używany tylko do sortowania. Indeks zaproponowany przez '@ op' może być użyty do filtrowania * i * do sortowania. Twój indeks nie może być używany do filtrowania, ale może (lub nie musi) być używany do sortowania. – Quassnoi

0

To powinno działać :

`select * from videos where approved='yes' and public_private='public' order by number_of_views desc;` 

Jeśli nie, po prostu utwórz oddzielny indeks na number_of_views.

To musi zadziałać.

(mysql następująca kolejność lewy-prawy zasadzie. Więc indeks approved, public_private, number_of_views nie będzie działać, jeśli nie są używane w tej kolejności, tj. Można użyć wszystkie trzy z lewej, 2 z lewej lub lewy najwyżej 1 Ale nie zadziała, jeśli nie użyjesz skrajnej lewej, to jest pomysł.)

Korzystanie z oddzielnego indeksu automatycznie sortuje number_of_views, może to pomóc w order by - jestem tego pewien.

+0

tylko dodanie indeksu 'number_of_views' nie rozwiąże problemu, ponieważ ten indeks będzie uważany za spełniający warunek' where'. W odpowiedzi PO należy używać indeksu 'approved_2', a nie indeksów na' approved, public_private' i 'number_of_views' oddzielnie. –