o_O. Простейший селект :(

  • Автор темы Автор темы cDLEON
  • Дата начала Дата начала

cDLEON

Онанист РНРСlub
o_O. Простейший селект :(

[sql]
CREATE TABLE `movies` (
`id` bigint(20) NOT NULL auto_increment,
`dirId` int(11) NOT NULL,
`movieName` varchar(40) collate utf8_bin default NULL,
`description` text collate utf8_bin NOT NULL,
PRIMARY KEY (`id`),
KEY `dirId` (`dirId`)
) ENGINE=MyISAM AUTO_INCREMENT=17 DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=17 ;
[/sql]
[sql]
EXPLAIN SELECT * FROM grabber_movies GROUP BY dirId
[/sql]
PHP:
 id  	 select_type  	 table  	 type  	 possible_keys  	 key  	 key_len  	 ref  	 rows  	 Extra
1  	SIMPLE  	grabber_movies  	ALL  	NULL  	NULL  	NULL  	NULL  	16  	Using temporary; Using filesort
 
Бггг...
Я думал и так понятно будет (
Запрос не использует индекс dirId :(
 
на 16-ти записях быстрее fullscan, что mysql и делает.
 
PHP:
1  	SIMPLE  	grabber_movies  	ALL  	NULL  	NULL  	NULL  	NULL  	2575  	Using temporary; Using filesort
Добавил записей...
 
1.
CREATE TABLE movies
EXPLAIN SELECT * FROM grabber_movies

2. Что должен делать этот запрос? Использование группировки в сочетании с SELECT * для меня выглядит бесмысленным.
 
мне нужно получить по одному мувику из каждой категории.

-~{}~ 01.08.08 19:41:

[sql]
EXPLAIN SELECT d.*,m.* FROM grabber_dirs as d LEFT JOIN grabber_movies as m ON m.dirId=d.id GROUP BY m.dirId
[/sql]
PHP:
1  	SIMPLE  	d  	ALL  	NULL  	NULL  	NULL  	NULL  	3  	Using temporary; Using filesort
1 	SIMPLE 	m 	ref 	dirId 	dirId 	4 	movie_grabber.d.id 	5
Вроде норм, только вот запрос 0.15 сек работает (((

-~{}~ 01.08.08 19:45:

Вопрос, кстати, не снят по поводу первого запроса... =))
 
Угу.. вот поэтому и плохо когда первый опыт с SQL приходит через MySQL.
По одному "мувику" из каждой категории это неправильный вопрос. Какому "мувику"? - последнему, самому популярному, и т.д.
Группируя по dirId вы должны использовать аггрегатные функции для всех полей не перечисленных в group
А ваша задача сводится к классическим top x for each category.
И самым быстрым решением будет денормализация и держать в отдельной таблице этот самый "мувик".

по поводу первого запрос вопрос снят, так как субд вообще не должна его обрабатывать.
 
Вопрос, кстати, не снят по поводу первого запроса...
что касается смысла самого запроса, то .des. правильно говорит о том что этого лучше не хотеть, не знаток в различных субд, но afaik postgres, mssql, oracle такой запрос не дадут выполнить. Mysql разрешает пока, но может в 6-ой версии сделают по умолчанию sql_mode=ONLY_FULL_GROUP_BY, как например и register_globals=off в php.

Если рассуждать почему не используется индекс.
Имхо, запрос предполагает чтение полностью всех данных таблицы. При использовании индекса - чтение данных будет происходить в случайном порядке (в порядке записей в индексе) и это чревато большим количеством операций IO (самое тормозное место обычно) по сравнению c последовательным чтением. Группировка 2.5K елементов в памяти вещь менее тормозная чем чтение этих данных с диска.
Хотя mysql мог бы делать и оптимизацию: сравнивать селективность индекса с общим количеством рядов, и если групп в разы меньше, то идти по индексу, читая только по одной строке данных (конечно будет считана не строка, а блок в N килобайт) для группы, всё равно не важно какие данные в этом случае :)
Но это всё лишь мои предположения.
Заставить использовать индекс можно с помощью force index(`index_name`)

[update]
выполнил несколько запросов на различных табличках,
запросы select * from `table`group by `field`, именно такой запрос понимается под "без force index".
На `field` во всех случаях был ключ.
Для проверки скорости с index сканом и без, форсировался индекс если explain говорил all или ignore index , если type=index:

1. таблица myisam ~700K записей, cardinality: 40000, Row_format=fixed.

a) без force index
time: 2 sec
explain: type=ALL; Using temporary; Using filesort

б) с force index()
time: 5.5 sec
explain: type=index

2. таблица myisam, 4M записей, cardinality: 20000, Row_format=fixed

a) без force index
time: 2 min 52 sec
explain: type=ALL, Using temporary, Using filesort
(добавление order by null и исчезновение Using filesort на скорость никак не влияло).

б) c force index
time: 56 sec
explain: type=index

3. таблица innodb, структура и данные аналогичные пункту 2

a) без force index
time: 1 min 13 sec
explain: type=index

б) c ignore index (чтоб был скан без индекса)
time: 3 min 35 sec
explain: type=ALL, Using temporary, Using filesort

4. запустил такие же тексты на innodb табличках 60K и 500K, всегда mysql предпочитал использовать индекс (и при его использовании запрос выполнялся быстрее) в отличие от myisam, видимо делается предположение что данные могут быть pool_buffer'е.
 
Сверху