2009-10-23 21 views
7

Mam stolik z 450000 rzędami pełnymi wiadomości. Schemat tabela jest tak:Konfiguracja indeksu Mysql

CREATE TABLE IF NOT EXISTS `news` (
    `id` int(11) NOT NULL auto_increment, 
    `cat_id` int(11) NOT NULL, 
    `title` tinytext NOT NULL, 
    `content` text NOT NULL, 
    `date` int(11) NOT NULL, 
    `readcount` int(11) NOT NULL default '0', 
    PRIMARY KEY (`id`), 
    KEY `cat_id` (`cat_id`), 
    KEY `cat_id_2` (`cat_id`,`id`), 
    KEY `cat_id_date` (`cat_id`,`date`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin5 AUTO_INCREMENT=462679 ; 

Kiedy uruchomić SQL polecenia jak poniżej, aby wziąć kilka nowości na stronie „x” od strony kategorii to trwa dłużej niż 15 sekund, jeśli x jest ponad 100:

select * news where cat_id='4' order by id desc limit 150000,10; 

wyjaśnienia wynika, że ​​jego pomocą „gdzie”, a indeks „cat_id_2”

pisząc to pytanie i sprawdziliśmy również bardziej proste zapytanie sql tak i on również zabrał blisko minutę:

select * from haberler order by id desc limit 40000,10; 

jeśli sql jest jak następujących jeden trwa zaledwie kilka milisekund:

select * from haberler order by id desc limit 20,10; 

Moja konfiguracja my.cnf jest tak:

skip-locking 
skip-innodb 
query_cache_limit=1M 
query_cache_size=256M 
query_cache_type=1 
max_connections=30 
interactive_timeout=600000 
#wait_timeout=5 
#connect_timeout=5 
thread_cache_size=384 
key_buffer=256M 
join_buffer=4M 
max_allowed_packet=16M 
table_cache=1024 
record_buffer=1M 
sort_buffer_size=64M 
read_buffer_size=16M 
max_connect_errors=10 
# Try number of CPU's*2 for thread_concurrency 
thread_concurrency=2 
myisam_sort_buffer_size=128M 
long_query_time   = 1 
log_slow_queries  = /var/log/mysql/mysql-slow.log 
max_heap_table_size=512M 

Strona działa na Core2Duo z 2 GB pamięci RAM. Myślę, że problem może być spowodowany przez sort_buffer_size, ale nie jestem pewien. z góry dzięki.

+0

Może być również indeksów, czy patrzeć w tym aspekcie? –

+0

W Twoim pytaniu jest kilka niespójności. Czy możesz go edytować, aby było bardziej zrozumiałe? –

+0

To musi być teraz naprawione, nazwy używane w tabeli były oryginalnie tureckie, wydaje się, że zapomniałem przetłumaczyć niektóre z nich na angielski. Przepraszam za mój zły angielski przy okazji. – intacto

Odpowiedz

17

Aktualizacja:

Zobacz artykuł w moim blogu na bardziej szczegółową analizę problemu:


Kiedy wydać coś takiego LIMIT 150000, 10, oznacza to, że MySQL powinien przechodzić przez te 150,000 zapisz i znajdź następny 10.

Przechodzenie przez indeks jest powolne w MySQL.

Ponadto, MySQL nie jest w stanie wykonać wyszukiwania w późnym wierszu.

Teoretycznie, jeśli nie ORDER BY id LIMIT 100000, 10, wystarczy użyć indeksu znaleźć wartości od 100000 do 100010, a następnie spójrz w górę tylko 10 wiersze, które spełniają, że indeks i ich zwrotu.

Wszystkie główne systemy z wyjątkiem MySQL są tego świadome i wyglądają na wiersze w górę tylko wtedy, gdy wartości mają zostać zwrócone.

MySQL, jednak wyszukuje każdy wiersz.

Spróbuj przepisać zapytanie jak to:

SELECT news.* 
FROM (
     SELECT id 
     FROM news 
     WHERE cat_id='4' 
     ORDER BY 
       id DESC 
     LIMIT 150000, 10 
     ) o 
JOIN news 
ON  news.id = o.id 
+0

Twoje zapytanie wydaje się działać znacznie szybciej, ale nie mogę zrozumieć przyczyny. Czy możesz również podać powód? – intacto

+1

Wyszukiwanie w późnym wierszu, opisałem to w moim poście. Moje zapytanie wybiera tylko rekordy "10" z samej tabeli, twoje pierwotne zapytanie wybiera wszystkie rekordy '150,000' i odrzuca je. Na ten wieczór zrobię bloga, w którym omówię go bardziej szczegółowo. – Quassnoi

+0

więc wzięcie just id sprawia, że ​​jest szybszy, rozumiem, dzięki .. – intacto

Powiązane problemy