Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: оптимизация
Форумы портала PHP.SU » PHP » SQL и Архитектура БД » оптимизация

Страниц (1): [1]
 

1. phpself - 22 Сентября, 2011 - 16:30:55 - перейти к сообщению
Добрый всем день Улыбка

есть такой запрос

CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. SELECT COUNT(IF(apremium > 0, 1, NULL)) AS premium_ads,
  3.             COUNT(*) - COUNT(IF(apremium > 0, 1, NULL)) AS ads_in_rub_with_premium,
  4.             COUNT(*) AS ads_in_rub,
  5.             (SELECT COUNT(*) AS number_ads FROM 1ads WHERE astatus > 0) AS ads_in_region
  6. FROM 1ads WHERE astatus > 0 AND adrub = 101
  7.  


как его можно оптимизировать ?
2. caballero - 22 Сентября, 2011 - 16:42:09 - перейти к сообщению
проследи чтобы в таблицах было индексы
и count лучше ставить индексное поле всесто *

adrub на это поле индекс поставь
3. phpself - 22 Сентября, 2011 - 16:49:31 - перейти к сообщению
caballero пишет:
проследи чтобы в таблицах было индексы
и count лучше ставить индексное поле всесто *

adrub на это поле индекс поставь


Спасибо, индексы уже где нужно проставлены. Заменил * на индексируемое поле как вы посоветовали. Сразу же протестировал, стало быстрей.

Я в этом запросе использую вложенный запрос. который из этой же таблицы делает выборку по другому параметру. Возможно в этом куске запроса можно что-то изменить ?
4. caballero - 22 Сентября, 2011 - 16:59:19 - перейти к сообщению
count по индексу читает быстро - хjтя это тупой оптиvизатор в mysql он должен был сам сообразить взять primary key

astatus здесь индекс попробуй поставить
5. phpself - 22 Сентября, 2011 - 17:11:44 - перейти к сообщению
caballero пишет:
count по индексу читает быстро - хjтя это тупой оптиvизатор в mysql он должен был сам сообразить взять primary key

astatus здесь индекс попробуй поставить


Спасибо за ответы Улыбка) В принципе производительность хорошая, просто думал что можно еще лучше сделать! Улыбка
6. MrBeard - 24 Сентября, 2011 - 21:25:38 - перейти к сообщению
caballero пишет:
проследи чтобы в таблицах было индексы
и count лучше ставить индексное поле всесто *

adrub на это поле индекс поставь

а разве ему нужен не индекс по двум полям? Мы же говорим про MySQL, не правда ли?
CODE (SQL):
скопировать код в буфер обмена
  1. WHERE astatus > 0 AND adrub = 101

INDEX my_table_index ( astatus, adrub);

и вообще, при просьбе оптимизации было бы интересно глянуть на explain, наверно. Плюс есть профайлинг для таких целей
7. Champion - 24 Сентября, 2011 - 21:40:24 - перейти к сообщению
MrBeard пишет:
WHERE astatus > 0 AND adrub = 101
INDEX my_table_index ( astatus, adrub);

тогда уж (adrub, astatus)
А explain и ddl таблиц не помешал бы.

Лучше всего иметь индексы по astatus, adrub и apremium (скорее всего отдельные)
И вытягивать все count(*) отдельными запросами. count(*) при наличии индексов сработает быстрее, чем count(выражение).

Плюс select count(*) from tbl where f > 0
иногда бывает полезно заменить на (select count(*) from tbl) - (select count(*) from tbl where f = 0 ), если f в таблице не имеет отрицательных значений, а нулей мало.

В любом случае нужно на конкретной вашей базе попробовать все варианты и выбрать наилучший.
8. MrBeard - 24 Сентября, 2011 - 21:45:38 - перейти к сообщению
Champion пишет:

тогда уж (adrub, astatus)

эм, с чего бы это? у него
1) последовательность запроса именно astatus, abrub;
2) подзапрос имеет WHERE astatus > 0;
как при этом получается индекс (adrub, astatus) ?
почитаю ка про оптимизатор мускулевый)

в принципе, могу предположить, что последовательность условий в where может поменять оптимизатор самой базы данных(надо бы проверить завтра), но тогда получится, что нужен отдельный индекс для astatus.
9. caballero - 24 Сентября, 2011 - 22:08:13 - перейти к сообщению
можно посмотреть план запроса
и вобщем то даже задать его
но то что нужен отдельный индекс по полю astatus вместо индекса по двум полям - это очевидно и так
10. Мелкий - 24 Сентября, 2011 - 22:15:36 - перейти к сообщению
MrBeard пишет:
эм, с чего бы это?

Потому что adrub - константа. Так как ключ упорядочен по значениям, запрос отсечёт моментально всё, не равное константе и останется только смотреть малый объём второй части ключа.
Иначе - придётся сначала искать все astatus>0 и в каждом искать adrub = константа.

MrBeard пишет:
в принципе, могу предположить, что последовательность условий в where может поменять оптимизатор самой базы данных

Смотрит и меняет всегда. Ещё на этапе разбора синтаксиса - хотя бы удостовериться, что запрос вообще имеет смысл, как то limit 0, where `a`=1 and `a`=2 и более хитрые варианты.

 

Powered by ExBB FM 1.0 RC1