Обновить

Комментарии 21

Однажды я поступил в универ на бюджет (математическая специальность), как потом выяснилось, решив задачу неправильно! После экзамена перерешал и понял где закралась ошибка. Сразу расстроился, думая что не поступил, т.к. без той задачи я уже не проходил по баллам. Но случилось странное как мне казалось тогда чудо - проверяющие почти не срезали за него баллы, т. к. в принципе правильных рассуждений в нём было достаточно много. Мораль, думаю, понятна.

вместе с заданием шел скрипт наполнения таблицы тестовыми данными, который я тут приводить не буду. Он основан на функции random и всё время будет выдавать разный набор.

Совершенно напрасно. Пусть не воспроизведётся один к одному ваш набор записей. но тенденции останутся практически неизменными. Миллиона записей достаточно, чтобы их выровнять. Опять же всегда можно перегенерировать набор (несколько раз, или расширить его) и повторить - общее останется, а случайные выбросы уйдут. А сейчас - голые слова.

Но постойте, ведь в задании сказано, что

Сообщения обрабатываются в порядке возрастания значения поля “process_date“.

Здесь же получается, что 3-е число еще не обработано, 4-ое обработано, а 5-ое снова не обработано.

Странно все это подумал я и решил, что данный факт просто опишу в решении.

Что вы нашли странного? То, что сообщение взято на обработку, не означает, что оно будет обработано ранее более позднего. Как и не означает, что оно будет обработано вообще. Вполне себе нормальная ситуация, которую вы почему-то решили проигнорировать. так что ответ про "несостыковки по части логики" - совершенно справедливо.

использование бесполезного rows only и fetch вместо limit.

Документация PostgreSQL практически открытым текстом говорит, что LIMIT и FETCH - это разные синтаксические формы одной и той же операции. SQL:2008 ввёл, Postgres взял под козырёк - и не более. В чём вы видите различие в полезности?

В задании ничего не сказано про специфику обработки. А я уж поверьте наелся очередей и прекрасно понимаю, что могут быть дырки.

Если читать мою статью внимательно, то у меня есть вариант, который это учитывает.

Про скрипт. Мне не хотелось выкладывать задание полностью. По понятным надеюсь причинам

FETCH в продакшене не видел ни разу, потому что есть новый limit

Это какой такой "новый"? Тот, который общеизвестен, появился гораздо раньше FETCH, уж в Постгрессе-то точно, так что это по сравнению с ним FETCH - новый.

Итак. fetch имеет смысл только with ties, который тут не нужен. Я, конечно, пошел и перечитал. Не уверен я, что даже вы прям все-все детали документации помните. Но суть моей статьи вообще не в этом. Вы б лучше, что-нибудь по делу сказали, чем цепляться за мелочи.

Не уверен я, что даже вы прям все-все детали документации помните.

Не поверите, но я, прежде, чем писать, тоже сначала освежил память чтением документации. И даже пробежался по изменениям в версиях.

Вы б лучше, что-нибудь по делу сказали

Вы проигнорировали особенности набора данных. У вас же вся статья построена на "у вас неправильный набор данных, я его поправлю, а потом буду решать". Я ничего не имею против ваших вариантов решения - кроме того, что они решают ДРУГУЮ задачу.

Опять же - вы смело вмешиваетесь в данные: "При этом сделал число 2026-01-04 не обработанным". Сразу возникает вопрос, почему вы столь же смело не вмешались в структуру? Так, как предложил @NeKukSA. На поверхности же плавает..

Нет, я понимаю, что вам обидно. Рассказываете в общем хорошую вещь, а вам тычут в несоблюдение условий. Но ведь оно - имеется, из песни слова не выбросишь.

Т.е. если запрос ничего не вернул, значит этот день полностью обработан и рекурсия останавливается.

А если имеется день без записей? Я не вижу в задании, что это невозможно. Этой возможности ваше первое решение, то, что с рекурсией, не учитывает.

Итак. fetch имеет смысл только with ties, который тут не нужен.

WITH TIES - это дополнительная, и да, весьма небесполезная, фича, но никто не обязывает ей пользоваться. А без неё LIMIT и FETCH - это по факту синонимы в PostgreSQL. И слышать, что решение, имеет или не имеет смысл конкретная операция, принимается на основании её синтаксической формы - несколько странно.

Вы проигнорировали особенности набора данных

Я хочу вас спросить. Вы видели запрос с рекурсией? Понимаете, чем он отличается от того для которого потребовалось изменить данные? Понимаете, что эти запросы вернут одно и то же? Я только до сих пор не понимаю, как действует мнимый обработчик. Поэтому варианта основных два.

А если имеется день без записей? 

А если кто-то другой загребет ту же запись? Тоже как бы по заданию можно предположить?

А если обработает, а признак не вернёт? Тоже по заданию...

Можно вас попросить проголосовать за неточность ТЗ?

Но ведь оно - имеется, из песни слова не выбросишь.

Там надо ускорить запрос, а не писать реальную очередь.

Не делал дополнительных и супер очевидных индексов только потому что в задании сказано изменить запрос. Изменить САМ запрос, чтобы он стал быстрей. Да и как вы, вероятно уже поняли, индексы нужно было не создавать, а убивать :) И последнее. Работа была 100% такая, что решение ускорить запрос индексом железобетонно не прокатило бы. Слишком уж просто.

Ну и кстати, в решении которое я им послал в пунктах ниже, были и индексы, и инклуды и даже партиции. Согласитесь, с партициями и индексы не нужны. Но все это было проигнорировано.

WITH TIES

Бог с ним. По настоящему это отношение к делу не имеет.

А почему не создать подходящий для запроса индекс? Копия уже имеющегося с условием

where status <> '10782572'::numeric

Индекс всегда будет содержать ссылки только на актуальные для шедулера строки, не будет занимать много памяти и не будет распухать при условии, что строки будут своевременно обрабатываться и автовакуум на базе не выключен)

Я бы начал разговор именно с такого предложения, даже выдумывать ничего не стал бы с запросом. Индексы - такой же инструмент, чего бы им не пользоваться.

Вы, конечно совершенно правы! Такой индекс всегда будет "в форме".

Но, в задании написано изменить сам запрос. И я чуть с дуба не рухнул, когда узнал, что изменить запрос у них означает выключить индекс вообще :)

То есть правильный ответ, с их точки зрения, это предварительный SET LOCAL enable_indexscan = off; , что ли? Бре-е-ед..

да, бред. думаю правильно:

drop index msg_idx;

create index msg_idx on msg (process_date) where status <> '10782572'::numeric;

в запрос добавить for no key update skip locked

лучше так:

CREATE INDEX msg_unprocessed_idx ON msg (process_date, id)
    WHERE status <> 10782572;

-- для очередей явно задавать порядок

id в include?

вряд ли, увеличится размер индекса; более сложно; там всего 100 строк; спросят что вы знаете о BitmapAnd. Про важность unit of order при обработке сообщений в очередях можно просто упомянуть

вряд ли, увеличится размер индекса

В этом индексе лежат только необработанные строки. А вот батч-выборка ORDER BY process_date, id — стабильная.

Если на одну дату десятки тысяч строк, тогда да, можно добавить id в order by. Не для спора, а чтобы всё учесть: досортировка не такая трудоемкая, индекс по одному столбцу будет дедуплицирован.

Ну да. С таким индексом никаких дополнительных плясок в коде не нужно. Это намного больше похоже на обработку очереди. Только в задании сказано тупо поменять запрос. Ой. Индекс выключить. Ой. Бог знает что сделать с дырками после обработки.

Я на самом деле не знаю, что было правильным ответом. Вот честно. Все что они мне сказали я тут привел. Но вот про мешающий индекс точно звучало. А я со стула упал.

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

Эх, не было у меня интервью. А в текстовом файле с решением были и индексы и партиции и еще много чего. Но все это было проигнорировано.

Отвечали мне в телеге. Все что ответили я описал своими словами

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации