Я работаю над мобильным веб-сайтом, популярность которого растет, и это приводит к росту некоторых ключевых таблиц базы данных - и мы начинаем видеть некоторые проблемы с производительностью при доступе к этим таблицам. Не будучи экспертами по базам данных (и не имея денег, чтобы нанять их на данном этапе), мы пытаемся понять, что вызывает проблемы с производительностью. Наши таблицы не такие большие , что , поэтому SQL Server должен уметь с ними справляться, и мы сделали все, что знаем, в плане оптимизации наших запросов. Итак, вот (псевдо) структура таблицы:
[user] (approx. 40,000 rows, 37 cols):
id INT (pk)
content_group_id INT (fk)
[username] VARCHAR(20)
...
[content_group] (approx. 200,000 rows, 5 cols):
id INT (pk)
title VARCHAR(20)
...
[content] (approx. 1,000,000 rows, 12 cols):
id INT (pk)
content_group_id INT (fk)
content_type_id INT (fk)
content_sub_type_id INT (fk)
...
[content_type] (2 rows, 3 cols)
id INT (pk)
...
[content_sub_type] (8 rows, 3 cols)
id INT (pk)
content_type_id INT (fk)
...
Мы ожидаем, что количество этих строк значительно возрастет (в частности, user, content_group и таблицы содержимого). Да, в пользовательской таблице довольно много столбцов - и мы определили некоторые, которые можно переместить в другие таблицы. Есть также несколько индексов, которые мы применили к затронутым таблицам, которые помогли.
Большие проблемы с производительностью - это хранимые процедуры, которые мы используем для поиска пользователей (которые включают присоединения к таблице содержимого в поле content_group_id). Мы пытались изменить предложения WHERE
и AND
, используя различные подходы, и мы думаем, что получили их настолько хорошо, насколько можем, но все же это слишком медленно.
Еще одна вещь, которую мы попробовали, но которая не помогла, это создать индексированное представление для таблиц пользователей и контента. Когда мы это сделали, заметного прироста производительности не было, поэтому мы отказались от этой идеи из-за дополнительного уровня сложности, присущего наличию слоя представления.
Итак, каковы наши варианты? Мы можем думать о нескольких, но все приходят с плюсами и минусами:
Денормализация структуры таблицы
Добавьте несколько ограничений прямого внешнего ключа между таблицами пользователя и контента - чтобы в таблице контента был отдельный внешний ключ для каждого подтипа контента.
Плюсы:
- Присоединение к таблице содержимого будет более оптимальным с использованием ее первичного ключа.
Минусы:
- Будет много изменений в наших существующих хранимых процедурах и коде сайта.
- Поддерживать до 8 дополнительных внешних ключей (более реалистично, мы будем использовать только 2 из них) будет не так легко, как текущий одиночный ключ.
Больше денормализации структуры таблицы
Просто скопируйте нужные нам поля из таблицы содержимого в таблицу пользователя напрямую.
Плюсы:
- Больше нет присоединений к таблице содержимого - что значительно сокращает работу, которую должен выполнить SQL.
Против
- То же, что и выше: дополнительные поля для поддержки в пользовательской таблице, изменения в SQL и коде веб-сайта.
Создание промежуточного слоя индексации
Используя что-то вроде Lucene.NET, мы поместили бы слой индексации над базой данных. Теоретически это повысит производительность всего поиска и одновременно уменьшит нагрузку на сервер.
Плюсы:
- Это хорошее долгосрочное решение. Lucene существует для улучшения производительности поисковой системы.
Минусы:
- В краткосрочной перспективе затраты на разработку будут намного выше, и мы должны решить эту проблему как можно скорее.
Итак, это то, что мы придумали, и на данном этапе мы думаем, что второй вариант самый лучший - я знаю, что у денормализации есть свои проблемы, однако иногда лучше пожертвовать архитектурной чистотой, чтобы получить повышение производительности, поэтому мы готовы оплатить эту стоимость.
Есть ли другие подходы, которые могут работать для нас? Есть ли какие-либо дополнительные плюсы и / или минусы с подходами, которые я изложил выше, которые могут повлиять на наши решения?