2010-09-27 4 views
1

Это скорее предпочтение, но мне было интересно, что люди считают оптимальным вариантом для выполнения. У меня есть вопрос, ответ, и точка (потому что мне нужно отслеживать, какой пользователь сделал пункт)DB Table Optimization join vs repeat columns

Таблица Dump

Question: 
    id 
    title 

Answer: 
    id 
    question_id 
    user_id 
    response 

Point_Answer: 
    id 
    answer_id 
    user_id 
    points 

Таким образом, в этой схеме, чтобы получить Top ответ потребует сложной последовательности соединения.

SELECT t2.id, t2.user_id, t2.response, MAX(points) 
FROM Question as t1, 
    (SELECT qa.*, SUM(pa.points) as points 
    FROM answer as qa, Point_Answer as pa 
    WHERE qa.id = pa.answer_id 
    GROUP BY qa.id) as t2 
WHERE t1.id = %s AND t1.id = t2.question_id 

Где, если я изменил его так:

Question: 
    id 
    title 

Answer: 
    id 
    question_id 
    user_id 
    response 
    points 

Point_Answer: 
    id 
    answer_id 
    user_id 
    points 

Запрос будет меньше обременять

SELECT A.id, A.user_id, A.response, MAX(points) 
FROM Question as Q, Answer as A 
WHERE Q.id = %s AND Q.id = A.question_id 
GROUP BY A.id 

Также будет означать, я бы убедиться, когда Point_Answer добавляется ответ. очки добавляются. Таким образом, в основном дополнительное ОБНОВЛЕНИЕ. В принципе, это «Целостность и избыточность» и немного оптимизация, каков будет лучший способ?

ответ

5

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

Если первое недопустимо медленное, то таблица или поле, суммирующие точки, могут быть приемлемой денормализацией, если и ТОЛЬКО, если вы сохраняете поле обновленным через триггер не из приложения (единственный способ обеспечить точность денормализованной номер). Вам нужно будет протестировать решение, включая дополнительное время обновления, чтобы определить, действительно ли вы сохранили время обработки. Это может зависеть от того, как часто меняются числа. FOr, если вы добавите секунду к времени обновления и сохраните десять секунд при выборе, но вам 10 000 обновлений для каждого selct это не очень хорошая оптимизация. Однако, если вы делаете отчет от часа до millseconds и добавляете только миллисекунду к вставке или обновлению, это может быть приемлемо.

Невозможно ответить на этот вопрос, фактически не кодируя и не тестируя оба решения с рабочей нагрузкой на уровне производства и данными.

+0

Хорошо, что имеет смысл, он еще не находится в развертывании, но задавался вопросом, с чего лучше всего начать. Я поеду с первой опцией и пойду честно. Если я увижу проблему позже, я всегда могу пойти на второй вариант. – Atherion

1

Если запрос выполняется достаточно хорошо, я оставил бы его как есть. Уродливый, эффективный запрос превосходит избыточность в моей книге.

С опцией избыточности вам необходимо убедиться, что вы инкапсулируете свои операторы обновления в транзакцию, чтобы убедиться, что все обновлено; в противном случае вы рискуете не синхронизировать свои данные.

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

2

Это зависит от многих факторов, большинство из которых зависят от вашей установки.

Двумя наиболее важными факторами являются:

  • Как часто вы запускаете запрос. Имейте в виду, что второе решение не только использует больше дискового пространства (что теоретически может снизить производительность), но также требует, чтобы вы занимались денормализованной структурой при добавлении записей. Хотя это можно было бы автоматизировать с помощью триггера (в зависимости от СУБД), это все еще является издержками производительности.
  • Используемые РСУБД. Ваш первый запрос может быть уродливым (я видел еще хуже), но уверены ли вы, что он медленный? Единственный способ получить окончательный ответ на этот вопрос - запустить запрос и проверить с помощью EXPLAIN [запрос], какой план запросов используется вашей РСУБД.

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

+0

Thx Chris, который помогает много. – Atherion