Оптимизация запроса

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

Solid

Drosera anglica
Оптимизация запроса

Запрос работает великолепно, только в 10 раз медленнее, чем надо. Пожалуйста, знающие люди, помогите, чем можете...

Код:
SELECT 
SQL_CACHE 
SQL_CALC_FOUND_ROWS 
artist.*, 
COUNT(DISTINCT album.album_id) AS artist_album_count, 
COUNT(DISTINCT song.song_id) AS artist_song_count, 
COUNT(DISTINCT lyric.lyric_id) AS artist_lyric_count, 
ROUND(SUM(song2rate.rate_count)/COUNT(song2rate.song_id)) AS artist_rate, 
COUNT(DISTINCT comment.comment_id) AS artist_comment_count 
FROM 
artist 
LEFT JOIN album ON artist.artist_id=album.artist_id 
LEFT JOIN song ON album.album_id=song.album_id 
LEFT JOIN lyric ON lyric.song_id=song.song_id 
LEFT JOIN song2rate ON song2rate.song_id=song.song_id 
LEFT JOIN comment ON comment.song_id=song.song_id 
WHERE 
artist.artist_name REGEXP '^a.*$' GROUP BY artist.artist_id 
ORDER BY artist.artist_name ASC

Все поля проиндексированны (используются все виды индексов unique, primary, index).
Используется mysql 4.1.
 
Solid, не надо тут сказки рассказывать. Regexp никогда не использует индексы. А like в этом случае долен бы.

2) зачем там SQL_CALC_FOUND_ROWS ?

3) я бы попробовал сделать составные индексы (song.album_id, song.song_id), (album.artist_id, album.album_id)

4) покажи, что говорит explain.
 
1) REGEXP работает немного медленнее LIKE, но всё же не так критично, как всё остальное. Падение производительности где-то всего лишь в двое.
2) Думаете просто так? Естественно в следующем запросе использую FOUND_ROWS().
3) Насколько составные индексы лучше обычных?
4)
Код:
id  	 select_type  	 table  	 type  	 possible_keys  	 key  	 key_len  	 ref  	 rows  	 Extra
1 	SIMPLE 	artist 	ALL 	NULL 	NULL 	NULL 	NULL 	4416 	Using where; Using temporary; Using filesort
1 	SIMPLE 	album 	ref 	artist_id 	artist_id 	4 	song2play.artist.artist_id 	12 	 
1 	SIMPLE 	song 	ref 	album_id 	album_id 	4 	song2play.album.album_id 	13 	 
1 	SIMPLE 	lyric 	ref 	song_id 	song_id 	4 	song2play.song.song_id 	12 	 
1 	SIMPLE 	song2rate 	ref 	song_id 	song_id 	4 	song2play.song.song_id 	12 	 
1 	SIMPLE 	comment 	ref 	song_id 	song_id 	4 	song2play.song.song_id 	15
 
1) т.е. тебя приходится уговаривать внять советам, которые тебе дают прирост производительности ВДВОЕ? на остальное отвечать даже не буду.
 
Да мне нужен REGEXP. Не хотите - не отвечайте, мне то что!? Я уверен, что вы и ничего дельного то посоветовать не можете.

-~{}~ 22.04.06 20:06:

Думаете я бы использовал REGEXP, если бы у меня была бы конструкция типа ^[a].*$? К примеру мне нужно использовать ^[0-9].*$, через LIKE это уже сделать невозможно. Да и суть то не в этом. Что REGEXP, что LIKE.. да что я в самом деле тут пытаюсь сказать, не хотите - не надо... всёравно не знаете, ибо, если бы знали - сказали бы.
 
ок.

1) зато с этим замечательно справится оператор =
where artist_name_first_letter in ('a')
where artist_name_first_letter in ('0', '1', '2', ...)

2)
Естественно в следующем запросе использую FOUND_ROWS().
Ну дак и используй. SQL_CALC_FOUND_ROWS то тут причем? (намкаю на то, что либо SQL_CALC_FOUND_ROWS вообще не нужен, либо приведенный пример не соответствует реальному запросу)

3)
Indexes are used for these operations:
...
* In some cases, a query can be optimized to retrieve values without consulting the data rows. If a query uses only columns from a table that are numeric and that form a leftmost prefix for some key, the selected values may be retrieved from the index tree for greater speed:
SELECT key_part3 FROM tbl_name WHERE key_part1=1
 
GROUP BY artist.artist_id
ORDER BY artist.artist_name

похоже даёт

Using temporary; Using filesort

попробуй убрать сортировку и померь, даст пищу для

а вообще тебе похоже нужно сильно денормализовывать чтобы не было динамического вычисления всех counters, и на artist.artist_name придется либо полный либо частичный индекс (первые несколько символов) - в зависимости от жесткости требований
 
fisher
Мне тоже кажется, что единственное решение всего этого безобразия возможно только через статику, т.е. высчитывать не в процессе выполнения запроса...
Что ж, Всем спасибо за участие.
 
Сверху