За последние 24 часа нас посетили 21492 программиста и 1022 робота. Сейчас ищут 825 программистов ...

Оптимизация COUNT

Тема в разделе "MySQL", создана пользователем S_t_e_e_p, 12 дек 2019.

  1. S_t_e_e_p

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

    С нами с:
    12 июл 2012
    Сообщения:
    181
    Симпатии:
    4
    Приветствую, есть 2 таблицы по 1 миллиону записей, запрос вида:

    Код (Text):
    1. SELECT COUNT(*) FROM products p
    2. LEFT JOIN product_descriptions pd ON p.product_id = pd.product_id
    3. WHERE pd.description != ''
    Запрос занимает 5с

    Возможно ли его как-то оптимизировать или нужно денормализацию делать?
     
  2. Artur_hopf

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

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    Ты этим милионом записей потом что делаешь?
     
  3. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    а с WHERE pd.id IS NOT NULL не будет быстрее?

    в общем случае, я бы при таких раскладах действительно попробовал завести счётчики как дополнительные поля чтобы пореже вызывать COUNT(*)
     
  4. ADSoft

    ADSoft Старожил

    С нами с:
    12 мар 2007
    Сообщения:
    3.822
    Симпатии:
    736
    Адрес:
    Татарстан
    Индексы в нужных полях надеюсь присутствуют?
     
  5. S_t_e_e_p

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

    С нами с:
    12 июл 2012
    Сообщения:
    181
    Симпатии:
    4
    индексы стоят на product_id в обеих таблицах. Я просто достаю инфу о кол-ве товаров, а так храню в редис кол-во, но приходится обновлять данные в кеше частенько
     
  6. Artur_hopf

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

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    Ну достал ты количество товаров, что с ними потом. Математика какая или просто отображаешь?
     
  7. S_t_e_e_p

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

    С нами с:
    12 июл 2012
    Сообщения:
    181
    Симпатии:
    4
    Для пагинации, чтобы расчитать кол-во страниц и вывода просто для инфы
     
  8. Artur_hopf

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

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
  9. Chushkin

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

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Про индексы...
    Здесь пересечение двух таблиц по миллиону. Если бы в product_descriptions не использовался индекс, то запрос выполнялся бы много много часов (миллион миллионов строк). А сколько именно - посчитай, или проверь. Потом расскажешь.
    ТС-у...
    Денормализация не обязательно, а вот кеширование подобных запросов на нужное тебе время самое оно.
     
  10. Artur_hopf

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

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    Ну я к тому что, не он первый кому надо сделать пагинацию. Явно есть решение, и скрывать зачем ему столько строк было не к чему.
     
  11. S_t_e_e_p

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

    С нами с:
    12 июл 2012
    Сообщения:
    181
    Симпатии:
    4
    Спасибо почитаю. Вообщем есть парсер который парсит товары вот после идет сброс кеша по ключу и это происходит каждые 8 часов или когда в админке удаляют товар. Так же я храню в кеше кол-во товаров в зависимости от фильтра который применили например отобразить все товары без категорий тут уже другое кол-во
    --- Добавлено ---
    Да вот кеширую запросы и просто храню число для каждого запроса
     
  12. Chushkin

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

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    >> Да вот кеширую запросы и просто храню число для каждого запроса
    Тогда твой вопрос не понятен.
    Ты хочешь избавиться от кеша для этих запросов?
     
  13. S_t_e_e_p

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

    С нами с:
    12 июл 2012
    Сообщения:
    181
    Симпатии:
    4
    Нет, просто происходит частое сбрасывание кеша, вот и думал как можно оптимизировать лучше
     
  14. Chushkin

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

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Кешируй не средствами MySQL. Тем более, в 8-ке они нагло его выкинули.
    Хотя тебе подойдёт самый простой вариант (без Memcashed и т.п.), - создай sql-табличку с тремя полями и пользуй её в качестве кеша. До 1000 запросов в секунду хватит, даже больше.
     
  15. qdevelopment

    qdevelopment Новичок

    С нами с:
    13 окт 2019
    Сообщения:
    41
    Симпатии:
    13
    Если знать количество строк необязательно, можно отказаться от COUNT и попробовать сделать пагинацию не в нумерованном виде 1 2 3 4, а кнопкой Далее.

    Допустим на страницу выводится 10 строк, запрашиваешь из базы 11 строк, дальше уже проверяешь, если в результате строк 11, показываешь кнопку Далее. И так с каждой страницей.
     
    #15 qdevelopment, 12 дек 2019
    Последнее редактирование: 12 дек 2019
  16. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    Возможно, только скорее всего бессмысленно. 10-50мс, которые не будут казаться тормозом на фронте ты не добьешься, потому всё равно придется так или иначе кэшировать. Если это метрика - просто посчитай и сохрани, для пагинации уходи в сторону предложения @qdevelopment с шагом через where id > X LIMIT Y (без offset).

    Ну а так, индексы по всем реально используемым в запросе полям, explain в попытках добиться того, что бы индексы применились, уменьшение полей используемых в запросе (т.е. не select *), возможно добавления оперативки планировщику, специфичные СУБД-фичи (типы индексов, какие-нибудь хитрые варианты запроса и т.п.) и местами денормализацию типа is_description_empty = true / false могут добить запрос до 200-400мс. Попробуй, такие заморочки как минимум полезны для наращивания скилла )
     
    artoodetoo и SProx нравится это.
  17. S_t_e_e_p

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

    С нами с:
    12 июл 2012
    Сообщения:
    181
    Симпатии:
    4
    Спасибо всем за ответы:)