Статистика

Участников проекта 105
Опубликовано статей 78
Отчет по карме. Топ 20

Новости блога

1 29.11.2013  Сегодня самым активным участникам newblog'а был выплачен доход с sape.
7 02.11.2012  Ура! Свешилось, нашему сайту дали тИЦ 10. Спасибо всем кто принимает участие в развитии нашего блога.
8 21.08.2012  Интеграция с sape.ru. Теперь каждый автор статей на newblog автоматически зарабатывает на рекламе.
Все новости

Топ 5 категорий

Программирование 46
Операционные системы 9
Базы данных 4
Туризм 2
Заметки 2

Последние 5 заметок (90)

gullyar - Закладки gullyar
gullyar - Ваша первая закладка
osadchaya - Закладки osadchaya
Ira0231188 - Закладки Ira0231188
Ira0231188 - Закладки Ira0231188

Ссылки

www.freedev.asia
Источник http://minsk1.net

select count from, paginator

14.10.2012 20:27 | Просмотров: 3864 | Доход: 65.52 руб. | Комментариев: 3
[Программирование] 
Рейтинг: 5/4

Работал над оптимизацией одного большого проекта и наткнулся на неворятно медленную пагинацию. Для тех кто в танке, paginator - это способ разбивки больших данных на страницы, чтобы отдавать данные порциями, а не целиком. Понятно, что пагинацию доверяют фреймворку только ленивые те, кто торопится что-то напрограммировать. Если капнуть глубже, то все постраничные пагинаторы устроены одинаково. Делается запрос, определяющий количество записей при определенных условиях, а затем подсчитывается количество страниц и пользователю отдается уже результат отработанный через limit. При разработке собственного пагинатора не стоит подгонять все запросы под одну гребенку, иначе рискуете нарваться на не составной индекс и тогда..

А тогда может получиться вот что:

select count(*) from table where table.parent_id=31334 and actual=1;


Сразу оговорюсь, оптимизация таких запросов важна в больших базах, к примеру в этой табличке больше 10 млн записей..
                        

+----------+
| count(*) |
+----------+
|     1406 |
+----------+
1 row in set (1.79 sec)

Капнув в explain, сразу видно в чем тут дело:

+----+-------------+-----------+-------------+---------------+---------------+---------+------+------+-------+
| id | select_type | table     | type        | possible_keys | key           | key_len | ref  | rows | Extra |
+----+-------------+-----------+-------------+---------------+---------------+---------+------+------+-------+
|  1 | SIMPLE      | table | index_merge | actual,ate_id | parent_id,actual | 8,1     | NULL | 4977 |  а тут..
+----+-------------+-----------+-------------+---------------+---------------+---------+------+------+-------+
Using intersect(parent_id,actual); Using where; Using index 

Через explain сразу видно, что попались несоставные индексы. Решений тут может быть несколько, в моем случае эффективнее было сделать составной запрос:

select count(*) from (SELECT id,actual FROM table WHERE table.parent_id=31334) as w where w.actual=1;
+----------+
| count(*) |
+----------+
|     1406 |
+----------+
1 row in set (0.01 sec)

 

Тоесть сначала выбираем все записи подходящие под условие, а затем убираем из них все неактуальные записи.

explain:
 

+----+-------------+------------+------+---------------+--------+---------+------+-------+-------------+
| id | select_type | table      | type | possible_keys | key    | key_len | ref  | rows  | Extra       |
+----+-------------+------------+------+---------------+--------+---------+------+-------+-------------+
|  1 | PRIMARY     | <derived2> | ALL  | NULL          | NULL   | NULL    | NULL |  6498 | Using where |
|  2 | DERIVED     | table  | ref  | parent_id        | parent_id | 8       |      | 11322 |             |
+----+-------------+------------+------+---------------+--------+---------+------+-------+-------------+

При таких запросах нужно быть внимательнее, такое может встречаться не только при пагинации с count(*), но также и при простой выборке.

И на последок, когда нужна "дикая" производительность в highload системах, лучше оказаться от ORM в пользу чистого sql. В cakephp например оставлена возможность использовать fetchAll и query, спасибо разработчикам фреймворка :)

"Should you need even more control over your queries, you can make use of prepared statements. This allows you to talk directly to the database driver and send any custom query you like"

http://book.cakephp.org/2.0/en/models/retrieving-your-data.html


© GM
| Комментировать статью |
  • Аноним 0 (04.11.2012 09:39)
    спасибо! взял на заметку
    | Ответить |
  • alexander +4 (14.11.2012 17:38)
    Прикольный способ, но вот что если неактуальных записей будет очень много?
    | Ответить |
    • GM +2587 (14.11.2012 22:38)
      Естественно все запросы нужно затачивать под конкретную бд и условия :)
      | Ответить |