Маловероятно, что в этом случае объединение будет слишком медленным, особенно если у вас есть индекс (вопрос) в таблице голосов.
Если он ДЕЙСТВИТЕЛЬНО слишком медленный, вы можете кэшировать счетчик голосов в таблице вопросов:
id - title - votecount
Вы можете обновлять счетчик голосов каждый раз, когда записываете голосование. Например, из хранимой процедуры или непосредственно из кода вашего приложения.
Эти обновления хитры, но, поскольку вы не так беспокоитесь о последовательности, я думаю, это нормально, если голосование иногда не совсем верно. Чтобы исправить любые ошибки, вы можете периодически восстанавливать все кэшированные данные, такие как:
UPDATE q
SET votecount = count(v.question)
FROM questions q
LEFT JOIN votes v on v.question = q.id
Совокупный счет (v.question) возвращает 0, если не было найдено ни одного вопроса, в отличие от count (*), который возвращает 1.
Если блокировки являются проблемой, рассмотрите возможность использования «with (nolock)» или «установить уровень изоляции транзакции для чтения без передачи» для обхода блокировок (опять же, на основании целостности данных, имеющей низкий приоритет.)
В качестве альтернативы nolock рассмотрим «моментальный снимок для фиксации чтения», который предназначен для баз данных с интенсивным чтением и меньшей активностью записи. Вы можете включить его с помощью:
ALTER DATABASE YourDb SET READ_COMMITTED_SNAPSHOT ON;
Доступно для SQL Server 2005 и выше. Это то, как Oracle работает по умолчанию, и это то, что использует сам stackoverflow. Об этом даже есть кодовая запись в блоге ужасов .