DISTINCT в SQL запросе метода string_query_list

MantisBT forum for users who prefer to ask and answer questions in Russian.

Moderators: Developer, Contributor

Post Reply
antifurer2
Posts: 2
Joined: 03 Nov 2020, 08:00

DISTINCT в SQL запросе метода string_query_list

Post by antifurer2 »

Добрый день
У нас долгое время был установлен багтрекер версии 2.5.1 (Schema Version - 209) с БД MySQL
В какой-то момент в связи с заключением контракта резко увеличилось кол-во созданных задач.
Раньше их всего было порядка 50 000.
За год их число выросло до 800 000 и будет дальше расти.
Когда их число начало расти возникли первые проблемы со скоростью работы. Почти сразу мы пришли к решению отключить рассылку почты полностью. Это ускорило обновление старницы при работе с отдельной задачей (редактирование, создание). Нас такой вариант устроил.
Но постепенно начали сильно тормозить две страницы - view_all_bug_page, my_view_page. Время загрузки этих страниц стало доходить до 14 секунд.
Мы решили попробовать перенести БД на Postgres (поскольку MySQL мы держали только для багтрекера, а везде стоял постгрес) и проапгрейдить сам багтрекер до версии 2.24.3.
Сначала мы портировали БД при помощи NMIG (пришлось, однако, изменить тип некоторых столбцов. В постгресе их сделало типом smallint, в то время как работало с ними как с boolean). Перешли на удивление быстро и просто. Однако это никак не повлияло на скорость загрузки.
Тогда мы проапгрейдили багтрекер. Это тоже не изменило скорость загрузки.
После этого мы стали логировать все запросы к БД и смотреть время загрузки.
Для загрузки страницы my_view_page необходимо 217 запросов.
Для загрузки страницы view_all_bug_page необходимо 43 запроса.
Слабым местом оказался вот такой SQL запрос :

Code: Select all

SELECT
    DISTINCT mantis_bug_table.*
FROM
    mantis_bug_table
    JOIN mantis_project_table ON mantis_project_table.id = mantis_bug_table.project_id
WHERE
    mantis_project_table.enabled = TRUE
    AND (mantis_bug_table.project_id = 2)
    AND (mantis_bug_table.status IN (10, 20, 30, 40, 50, 80))
ORDER BY
    mantis_bug_table.sticky DESC,
    mantis_bug_table.last_updated DESC,
    mantis_bug_table.date_submitted DESC
LIMIT
    50 OFFSET 0
На продакшн базе он выполняется 13 секунд.

А теперь, собственно, вопрос:
В представленном выше запросе вначале стоит слово DISTINCT. Если убрать это слово из запроса, то запрос обрабатывается за 1.5-2 секунды. Это уже приемлемое время.
Этот запрос генерируется в классе BugFilterQuery.class.php в методе string_query_list()
Я локально поднял у себя копию базы и багтрекер. И в этом методе удалил ключевое слово DISTINCT из запроса. Результат меня порадовал - страницы грузятся за 1.5-2 секунды. При этом я пока не заметил никаких проблем. Выборка, работа с задачами, фильтры - все работает корректно.
1) Есть ли необходимость в этом ключевом слове в данном месте?
2) Что может плохого произойти, если я оставлю этот метод в таком виде без слова DITINCT? Какие ошибки я могу получить? У нас нет никаких custom fields. Есть несколько проектов.
3) В запросе выше слово DISTINCT не несет никакой смысловой нагрузки, поскольку выборка идет из таблицы mantis_bug_table, в которой и так каждая задача имеет уникальный ID. Или я в этом утверждении не прав?
4) Может есть другие варианты решения данной проблемы? Но методом исключения я уперся именно в этот SQL запрос. Сомневаюсь, что какие-то другие изменения дадут такое улучшение.

Заранее спасибо за ответы. Я пока на продакшне ничего не меняю. Хотелось бы узнать, может я сделаю большую ошибку.
Kirill
Posts: 616
Joined: 25 Nov 2007, 08:05
Location: Kaliningrad, RF
Contact:

Re: DISTINCT в SQL запросе метода string_query_list

Post by Kirill »

По работе в высоконагруженных системах я не подскажу. Тут лучше решать каждый вопрос индивидуально. Что касается конкретно этого случая, то в текущем варианте DISTINCT в запросе никак не влияет. И если его убрать ничего не поменяется. Но ведь этот запрос не в прямом виде храниться в ходе, а вызывается функция, которая этот запрос составляет. Вопрос где еще может быть вызван этот конструктор, который составляет запрос с уникальными записями. В лучшем случае он просто выведет данные в виде нескольких строчек. В худшем он сломает верстку и мантис будет недоступен, но данные точно не поломает.
Попробуйте сформировать plan запроса. Может какой-то индекс проще добавить?
antifurer2
Posts: 2
Joined: 03 Nov 2020, 08:00

Re: DISTINCT в SQL запросе метода string_query_list

Post by antifurer2 »

С индексом я пробовал. Не сильно лучше получается.
Тут сам запрос мне кажется как-то то ли с запасом сделан. Я пока не придумал ситуацию, когда там дубли могут появиться, чтобы DISTINCT отработал.
Запрос формируется в классе BugFilterQuery. И насколько я смог понять, анализируя код, то используется он только при фильтрации выборки (что следует из названия).
У меня еще есть мысль перегнать все решенные задачи в отдельно созданный проект. Тогда в этом останутся нерешенные и работать будет на порядок быстрее. Единственный минус - для пользователя надо объяснить, что его задачи хранятся в двух проектах. В основном они в решенные уже не лезут. А выборку для анализа я все равно делаю напрямую из базы :wink:
Посовещаемся и будем пробовать наверно на продакшене 8O
По результатам отпишусь
Kirill
Posts: 616
Joined: 25 Nov 2007, 08:05
Location: Kaliningrad, RF
Contact:

Re: DISTINCT в SQL запросе метода string_query_list

Post by Kirill »

Можно не все решенные переносить в архив, а, например, 2х-месячной давности.
Post Reply