(field2, field3) from base where filed = "value"
в случае этого запроса будет выбрано 14 млн строк. при таком запросе очень нагружается cpu и i/o.
что можно сделать для оптимизации?
окей, можно сделать индексы на поля field2, field3. но что еще?
поможет ли limit в данной ситуации?
не понял смысл вопроса. выбирается 14 млн из общей базы для дальнейшей работы с этими данными
потому что они подходят под фильтр) все данные - нужные
прямо здесь и сейчас?
да. т.к. тут 20 сек мута, напишу в этом сообщении. это не однотипная задача. бизнес-логика проекта большая, выборки - тоже большие. что с этими данными происходит - это другой вопрос. просто есть факт большой выборки
ваш сервер с бизнес логикой сможет сразу переворить 14 милионов записей?
ну окей. завтра будет 100 млн. данные, уникальные. и как быть то с этим всем? к примеру, есть 100 млн. человек. система должна выбрать их всех и как-то обработать. как в такой ситуации быть?
Выбирать курсорами. Зачем вам 100 миллионов тянуть в память?
супер. уже что-то. не знал про них. сейчас почитаю. спасибо
Что значит "обработать"? Они как-то друг с другом связаны, при обработке одного вам могут понадобиться данные другого? Если нет - то обрабатывайте их последовательно, пачками по миллиону например, или как вам там удобно. Если да - то либо переносить логику обработки ближе к данным (т.е. обрабатывать прямо в БД хранимками) либо всё таки тащить все целиком.
> при таком запросе очень нагружается cpu и i/o. Хмм... а Вы чего ожидали, извините? Что PostgreSQL возьмёт данные из воздуха (прочитать-то их нужно, правда)? ;) > поможет ли limit в данной ситуации? У Вас и проблемы-то нет, по-моему. Чтобы выдать данные как можно быстрее, PostgreSQL использует имеющиеся ресурсы, и это нормально. Вы, что, хотите, чтобы всё работало помедленнее (а disk, CPU и RAM в этот сервер вставлены для того, чтобы ими любоваться?). ;) Кроме шуток, лучшего по производительности, чем с index-only scan, тут не добьёшься. Если Вам почему-то нужно экономить ресурсы — сам PostgreSQL таким не занимается, нужно что-то внешнее (но зачем?!).
посмотрел один из кусков кода. упрощенно: берутся записи товаров из бд. сервис их как-то обрабатывает и дополняет. дальше эти данные летят в кафку для других сервисов. я не особо понимаю, при чем тут бизнес-логика, т.к. я сказал про факт того, что данные выбираются по критериям, они нужные, и их не становится меньше
всё целиком не обязательно тащить. для порционной выборки подойдут только курсоры?
Я бы сделал условие вида id > N и LIMIT добавил. N увеличивал бы на каждой итерации
это на уровне бд делается, верно? если да, то печаль
а вы на чём обработку пишете-то?
бизнес-логика на go
эх, спасибо. тогда пойду выбивать их инженеров секционирование
А ведь это, скорее всего, не поможет — только время зря потратите. Впрочем, дело Ваше...
к сожалению, не глубоко изучил проблему) признаю
Тут я склонен согласиться, и я бы все-таки предложил обновлять частями, по скажем 10к товаров выбирая, как предложили выше по id > ... limit 10000
так всё таки лимит снизит нагрузку? я как понял из ответа Ярослава, она не даст результата по кушанию ресурсов
У меня тут много вопросов возникает. 1) вам нагрузка не нравится, потому что она идёт скачками (в период выполнения тяжёлого запроса) и влияет на выполнение других запросов? Если так, то высасывать данные пачками по 10-100к - нормальный вариант. Можно хоть thread.sleep делать между итерациями. Но нужно придумать, как определять, какие данные уже были выбраны, чтоб эта схема оказалась не *N(батчей) по ресурсоемкости от текущего варианта. 2) эти 14 миллионов записей каждый раз разные? Или постоянно одни и те же данные выбираются, потому что нет инкрементальности? Если так, то добавление инкрементальности в схему/запрос - скорее всего лучшее решение
я правильно же понимаю, что под пачками имеется ввиду limit? но да, при таких скачках у нас "тупят" другие запросы. и что есть инкрементальность, простите за вопрос?)
Либо потоково читать, да, как уже выше советовали, и обрабатывать каждую запись на лету, без сохранения в память клиента всех данных. Но это в основном повлияет на потребление памяти, о котором в изначальном вопросе вроде не говорилось)
Limit в каком-то виде, да. Про инкреметальность - насколько я понял ваш вопрос, клиент регулярно высасывает 14 миллионов записей. Вопрос возникает, что это за записи - все 14 миллионов каждый раз новые, или это одни те же записи с небольшими изменениями, которые каждый раз целиком выбираются из базы и где-то ниже по пайплайну diff'аются с предыдущей выборкой
И на диск и на проц сервера БД так же влияет, так как положить все данные в память требуется их прочитать с диска сначала. Курсоры этого не наделают а читают последовательно при Next.
по идее, данные могут меняться, не все, частями и не всегда
Если клиент очень быстро обрабатывает (типа просто шлёт кафку все сразу), то кажется все равно могут быть проблемы. Но у меня мало опыта с курсорами, может они прям божественно работают для такого кейса)
Ну вот, идея про инкреметальность - добавить признак, по которому можно понять, изменилась запись с последнего запроса или нет. Можно заюзать sequence, например
Обсуждают сегодня