За последние 24 часа нас посетили 21809 программистов и 846 роботов. Сейчас ищут 677 программистов ...

count(*) vs SQL_CALC_FOUND_ROWS

Тема в разделе "MySQL", создана пользователем armadillo, 12 ноя 2007.

  1. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    собственно нашел узкое место.
    [sql]SELECT cl.cl_id, cl.cl_reger_id, us.us_fio,
    cl.cl_reg_date, cl.cl_fio, cl.cl_proced,
    cl.cl_status, cl.cl_tipon, obn0.on_id
    group_concat( concat( '(', ph_code, ')', ph_number ) SEPARATOR ', ' ) as ph
    FROM clients cl, users us
    LEFT JOIN obn obn0 ON obn0.on_cl_id=cl.cl_id
    LEFT JOIN obn obn1 ON obn1.on_cl_id=cl.cl_id AND obn1.on_id>obn0.on_id
    LEFT JOIN phones ON ph_cl_id = cl_id

    WHERE cl.cl_id != 0
    AND cl.cl_reger_id=us.us_id AND obn1.on_id is null
    GROUP BY cl.cl_id DESC[/sql]

    листалка добавляет limit и SQL_CALC_FOUND_ROWS для подсчета общего количества. Одноко добавление SQL_CALC_FOUND_ROWS превращает время выполнения из 0.02 в 3.3-3.5 сек (целерон)
    полез в ПМА, там стараются использовать count(*)
    но это не проходит в данном случае из-за group by (может и туплю)
    вместе с тем сам ПМА нормально по времени считает общее количество для этого запроса.
    как именно - непонятно, там надо глубоко копать.

    погуглил, нашел только это http://xpoint.ru/forums/computers/dbms/ ... 6077.xhtml
    тут предлагают переделывать на count(distinct ...) но непонятно что при наличии еще условия group by или having и какой это надо громоздить парсер запросов для листалки.
     
  2. Clone

    Clone Guest

    Не очень понимаю что выполняет данный запрос, но тупо взять количество рядов можно mysql_num_rows...
     
  3. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    угу, ты не понял.
    Есть запрос, который выполняется по большой базе (результаты поиска с листалкой).
    с лимитом он выполняется быстро. Весь без лимита - крайне медленно (поэтому и mysql_num_rows не подойдет - для этого надо сначала выбрать всю базу)

    я передаю листалке этот запрос, она формирует ему лимит и возвращает нужную страницу. Вопрос как узнать общее число записей по этому условию. в MySQL для этого есть ключевое слово SQL_CALC_FOUND_ROWS, у меня листалка добавляет его в запрос (SELECT SQL_CALC_FOUND_ROWS cl.cl_id,...) и после него командой found rows получает общее число записей.
    Однако на большой базе это здорово тормозит, примерно так же, как с запросом без лимита.
    Обычно намного быстрее будет использовать отдельный запрос с count(*)

    В этом запросе он не работает - мешает group by, подсчитывается не то.
     
  4. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    armadillo
    А можешь сделать копию базы и дать доступ в PMA? Я с такими запросами намучался дофига - смогу помочь, просто данные перед носом очень хорошо иметь :)
     
  5. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    напрямую - не могу, но структура из запроса понятна. phones - varchar 3 ph_code и varchar 7 ph_number
    объемы таблиц в пределах 100к записей.
    в общем пока добавил в листалку возможность добавления второго запроса для подсчета, если пустой - использовать SQL_CALC_FOUND_ROWS
    по этому запросу - переделал group by на count(distinct), стало быстрее, хотя и все равно стоит улучшить.

    [sql]SELECT count( DISTINCT cl.cl_id )
    FROM clients cl
    LEFT JOIN obn obn0 ON obn0.on_cl_id=cl.cl_id
    LEFT JOIN obn obn1 ON obn1.on_cl_id=cl.cl_id AND obn1.on_id>obn0.on_id
    LEFT JOIN phones ON ph_cl_id = cl_id

    WHERE cl.cl_id != 0
    AND obn1.on_id is null[/sql]

    И непонятно что делать при наличии having
     
  6. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    все равно время выполнения запроса с лимит и с count отличается на два порядка (zend profile)