2009-10-23 15 views
7

Ich habe eine Tabelle mit 450000 Reihe voller Nachrichten. Das Tabellenschema ist wie folgt:Mysql Index Konfiguration

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 ; 

Wenn ich führe einen SQL-Befehl wie unten einige Nachrichten für eine Seite zu nehmen „x“ der Kategorieseite es mehr als 15 Sekunden in Anspruch nimmt, wenn x über 100:

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

erklären zeigt, dass seine Verwendung von „wo“ und der Index „cat_id_2“

Während diese Frage schreibe ich eine einfache sQL-Abfrage wie dies auch überprüft, und es dauerte auch in der Nähe einer Minute:

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

, wenn die SQL ist wie die folgenden es dauert nur wenige Millisekunden:

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

Meine my.cnf Konfiguration ist wie folgt:

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 

Die Website auf einem Core2Duo läuft mit 2 GB RAM. Ich denke, dass das Problem durch die sort_buffer_size verursacht werden kann, aber ich bin mir nicht sicher. danke im voraus.

+0

auch Ihre Indizes sein könnte, haben Sie diesen Aspekt prüfen? –

+0

Es gibt eine Reihe von Inkonsistenzen in Ihrer Frage, bitte können Sie sie bearbeiten, um sie klarer zu machen? –

+0

es muss jetzt behoben werden, die Namen in der Tabelle verwendet wurden ursprünglich türkisch, scheint wie ich vergaß, einige von ihnen auf Englisch zu übersetzen. Entschuldigung für mein schlechtes Englisch übrigens. – intacto

Antwort

17

Update:

diesen Artikel in meinem Blog sehen für die detaillierte Analyse des Problems:


Wenn Sie so etwas wie LIMIT 150000, 10 ausgeben, es bedeutet, dass MySQL diesedurchlaufen sollteAufzeichnungen und finden Sie die nächste 10.

Das Verfolgen des Index ist in MySQL langsam.

Auch MySQL ist nicht in der Lage, Late-Lookups zu tun.

Theoretisch, wenn Sie ORDER BY id LIMIT 100000, 10 tun, ist es genug, um den Index zu verwenden, um die Werte 100000-100010 zu finden, dann nur 10 Zeilen suchen, die diesen Index erfüllen und sie zurückzukehren.

Alle größeren Systeme außer MySQL sind sich dessen bewusst und schauen die Zeilen nur dann an, wenn die Werte wirklich zurückgegeben werden sollen.

MySQL sucht jedoch jede Zeile nach.

Versuchen Sie Ihre Frage, da dies zu umschreiben:

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

Ihre Abfrage scheint viel schneller zu arbeiten, aber ich kann den Grund nicht verstehen. kannst du bitte auch den Grund angeben? – intacto

+1

Späte Zeilensuche, ich habe das in meinem Post beschrieben. Meine Abfrage wählt nur '10' Datensätze aus der Tabelle selbst, Ihre ursprüngliche Abfrage wählt alle '150.000' Datensätze aus und verwirft sie. Ich werde an diesem Abend einen Blogeintrag machen, in dem ich ausführlicher darüber sprechen werde. – Quassnoi

+0

so nehmen nur ID macht es schneller, habe es, danke .. – intacto