Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: problem z zapytaniem i użyciem kluczy
Forum PHP.pl > Forum > Bazy danych > MySQL
ChrisB
witam
zauważyłem jakiś czas temu u siebie dużą wielkość Handler_read_rnd_next, po około godzinie pracy serwera: 2 530 k

i teraz, włączyłem logowanie do pliku zapytań nie wykorzystujących poprawnie indexów, z bardziej rażących przykładów:

tabela ranking:

  1. CREATE TABLE `ranking` (
  2. `id_uzyt` mediumint(7) NOT NULL DEFAULT '0',
  3. `grupa` smallint(6) NOT NULL DEFAULT '0',
  4. `data` date DEFAULT NULL,
  5. `wartosc_portfela` double(13,2) NOT NULL DEFAULT '0.00',
  6. `miejsce` smallint(6) NOT NULL DEFAULT '0',
  7. `miejscepop` smallint(6) NOT NULL DEFAULT '0',
  8. `login` char(20) collate utf8_polish_ci NOT NULL DEFAULT '',
  9. `procentinv` float(4,2) NOT NULL DEFAULT '0.00',
  10. `zmianawart1` float(6,2) NOT NULL DEFAULT '0.00',
  11. `zmianawart2` float(6,2) NOT NULL DEFAULT '0.00',
  12. `miejscetydz` mediumint(9) NOT NULL,
  13. `zmianawart3` float(6,2) NOT NULL DEFAULT '0.00',
  14. `miejscemies` mediumint(9) NOT NULL,
  15. KEY `miejsce` (`miejsce`),
  16. KEY `id_uzyt` (`id_uzyt`),
  17. KEY `grupa` (`grupa`)
  18. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci;



zapytanie:

  1. mysql> explain select * from ranking order by miejsce ASC limit 8300,100;
  2. +----+-------------+---------+-------+---------------+---------+---------+------+------+-------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+---------+-------+---------------+---------+---------+------+------+-------+
  5. | 1 | SIMPLE | ranking | index | NULL | miejsce | 2 | NULL | 8472 | |
  6. +----+-------------+---------+-------+---------------+---------+---------+------+------+-------+
  7. 1 row in set (0.00 sec)


całkowita liczba rekordów 8472 - skanuje je wszystkie by podać mi wynik

i teraz pytanie brzmi co robię źle?
byłbym wdzięczny za jakieś wskazówki
pozdrawiam
Mchl
Nic. Nie ma innej możliwości posortowania wszystkich wierszy w tabeli jak tylko przez posortowanie wszystkich wierszy w tabeli.

Poza tym zauważ, że zapytanie wykorzystuje indeks `miejsce`
wookieb
A co długo się wykonuje? Nie zapytanie nie wykorzystuje do końca indeksu.

  1. EXPLAIN SELECT * FROM tabela ORDER BY miejsce ASC

To wykorzysta index pod warunkiem, że będzie na tym polu założony
  1. EXPLAIN SELECT miejsce FROM tabela ORDER BY miejsce ASC
ChrisB
nie, nie wykonuje się długo, ale za to często, i wylądowało w logu powolnych zapytań i tych które nieprawidłowo używają kluczy (robią full table scan)
łącznie serwer zaczyna przymulać, i ta wartość Handler_read_rnd_next rośnie szybko (gdzie powinna być naprawde niska)

w każdym razie teraz inny przykład:

  1. # Query_time: 0 Lock_time: 0 Rows_sent: 449 Rows_examined: 950
  2. select id_not,krotka,kurs,ostzamkniecie,volumen from notowania where branza>0 order by krotka;
  3.  


  1. mysql> SHOW INDEX FROM notowania;
  2. +-----------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
  3. | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
  4. +-----------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
  5. | notowania | 0 | PRIMARY | 1 | id_not | A | 501 | NULL | NULL | | BTREE | |
  6. | notowania | 0 | KROTKA | 1 | krotka | A | 501 | NULL | NULL | | BTREE | |
  7. | notowania | 1 | branza | 1 | branza | A | 5 | NULL | NULL | | BTREE | |
  8. | notowania | 1 | nazwa_akcji | 1 | nazwa_akcji | A | 501 | NULL | NULL | | BTREE | |
  9. | notowania | 1 | zmiana | 1 | zmiana | A | 250 | NULL | NULL | | BTREE | |
  10. +-----------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+



wysłało 449, zbadało 950 - przy łącznej ilości rekordów - 501 w bazie

i jeszcze explain:
  1. mysql> explain extended select id_not,krotka,kurs,ostzamkniecie,volumen from notowania where branza>0 order by krotka;
  2. +----+-------------+-----------+------+---------------+------+---------+------+------+-----------------------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-----------+------+---------------+------+---------+------+------+-----------------------------+
  5. | 1 | SIMPLE | notowania | ALL | branza | NULL | NULL | NULL | 501 | Using where; Using filesort |
  6. +----+-------------+-----------+------+---------------+------+---------+------+------+-----------------------------+
  7. 1 row in set, 1 warning (0.00 sec)

Mchl
Cytat(wookieb @ 20.05.2010, 16:30:20 ) *
A co długo się wykonuje? Nie zapytanie nie wykorzystuje do końca indeksu.

  1. EXPLAIN SELECT * FROM tabela ORDER BY miejsce ASC

To wykorzysta index pod warunkiem, że będzie na tym polu założony
  1. EXPLAIN SELECT miejsce FROM tabela ORDER BY miejsce ASC


A dokąd go wykorzystuje jak nie do końca?

select_type - SIMPLE (Simple SELECT)
type - index (This join type is the same as ALL, except that only the index tree is scanned. This usually is faster than ALL because the index file usually is smaller than the data file. )
key - miejsce
key_len - 2

Zmiana powyżej miałaby sens na silniku InnoDB [dodane] No dobra. W MyISAM też, jeśli rzeczywiście potrzebna jest tylko ta jedna kolumna.


Kod
select id_not,krotka,kurs,ostzamkniecie,volumen from notowania where branza>0 order by krotka;

Spróbuj założyć indeks na kolumny (branza,krotka)
ChrisB
wposcie powyżej wypisałem indeksy z tabeli
id_not, krotka, branza, nazwa_akcji, zmiana - mają nałożone indeksy
tabela ma ponad 80 kolumn więc strukture sobie podaruje
Mchl
Ale nie ma tam indeksu obejmującego obie te kolumny.
http://dev.mysql.com/doc/refman/5.0/en/mul...mn-indexes.html
ChrisB
człowiek uczy się czegoś co chwilę, nawet nie wiedziałem że tak można:P
w każdym razie:


  1. +----+-------------+-----------+------+-----------------+------+---------+------+------+-----------------------------+
  2. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  3. +----+-------------+-----------+------+-----------------+------+---------+------+------+-----------------------------+
  4. | 1 | SIMPLE | notowania | ALL | branza,branza_2 | NULL | NULL | NULL | 501 | Using where; Using filesort |
  5. +----+-------------+-----------+------+-----------------+------+---------+------+------+-----------------------------+



  1. mysql> SHOW INDEX FROM notowania;
  2. +-----------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
  3. | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
  4. +-----------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
  5. | notowania | 0 | PRIMARY | 1 | id_not | A | 501 | NULL | NULL | | BTREE | |
  6. | notowania | 0 | KROTKA | 1 | krotka | A | 501 | NULL | NULL | | BTREE | |
  7. | notowania | 1 | branza | 1 | branza | A | 5 | NULL | NULL | | BTREE | |
  8. | notowania | 1 | nazwa_akcji | 1 | nazwa_akcji | A | 501 | NULL | NULL | | BTREE | |
  9. | notowania | 1 | zmiana | 1 | zmiana | A | 250 | NULL | NULL | | BTREE | |
  10. | notowania | 1 | branza_2 | 1 | branza | A | 5 | NULL | NULL | | BTREE | |
  11. | notowania | 1 | branza_2 | 2 | krotka | A | 501 | NULL | NULL | | BTREE | |
  12. +-----------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+


chyba dalej coś do końca nie jest tak jak powinno
wookieb
Zeby w tym zapytaniu był użyty tylko indeks, musisz mieć założone indeksy na wszystkie kolumny które pobierasz, filtrujesz i sortujesz.
Ale to raczej nie na tym polega...
To że wykonują się często to jedna sprawa, na twoim miejscu pomyślałbym po prostu o cache po stronie php.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.