простой вопрос о дизайне таблицы

Я пытаюсь предположить немного и избежать меня некоторая дополнительная боль, если это возможно.

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

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

+-----+---------+------------+-------+--------+-------+
| id  | room_id | bookdate   | price | people | total |
+-----+---------+------------+-------+--------+-------+
| 414 | 132     | 2010-03-01 | 14.55 | 2      | 29.10 |
| 415 | 132     | 2010-03-02 | 14.55 | 2      | 29.10 |
| 416 | 132     | 2010-03-03 | 14.55 | 2      | 29.10 |
+-----+---------+------------+-------+--------+-------+

Информация в последнем поле могла быть извлечена из продукта предыдущих двух, поэтому это является избыточным и ненужным. Есть ли экземпляры, когда могло все еще стоить иметь его?

7
задан holden 2 February 2010 в 17:04
поделиться

11 ответов

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

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

6
ответ дан 6 December 2019 в 10:50
поделиться
[113042635-

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

2
ответ дан 6 December 2019 в 10:50
поделиться

Может быть, создать таблицу, содержащую все поля, кроме последнего, а затем создать представление, которое содержит все поля и автоматически подсчитывает последние поля?

Таким образом, таблица будет содержать только эти поля

+-----+---------+------------+-------+--------+
| id  | room_id | bookdate   | price | people | 
+-----+---------+------------+-------+--------+
| 414 | 132     | 2010-03-01 | 14.55 | 2      | 

И определение представления, которое вычисляет сумму, также очень простое:

select *, price*people as total  from rooms

(при условии, что ваша таблица называется rooms

4
ответ дан 6 December 2019 в 10:50
поделиться

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

create table rooms (
    price numeric, 
    people numeric, 
    total numeric check (total=price*people));

Это добавит небольшие накладные расходы на вставки и обновления.

2
ответ дан 6 December 2019 в 10:50
поделиться

Я бы пошел вперед и поставить в полное поле. Из того, что я вижу здесь, нет «скидки» или аналогичного поля, которое может снизить общее количество, но я могу представить сценарии, где цена * количество людей может не равняться общему количеству. Возможно, вы захотите рассмотреть поле комментариев или даже таблицу, чтобы позволить кому-то отметить , почему Всего не соответствует продукту других полей.

Доля и наслаждайтесь.

0
ответ дан 6 December 2019 в 10:50
поделиться

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

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

-121--3842637-

Это очень похоже на этот вопрос, и ответы могут быть полезны для вас: Компилятор для перевода Java на C .

Краткое описание: Для этого существуют инструменты (Toba, GCJ и т.д.), но при портировании не всех библиотек Java могут возникнуть проблемы. В конце концов, инструменты, вероятно, будут выполнять только ЧАСТЬ работы, и вам придется вручную кодировать часть остальных.

Хорошим первым шагом является преобразование кода Java для использования только стандартных библиотек, доступных в Java 1.4. На самом деле, вы, вероятно, захотите отучить как можно больше от чего-либо, кроме пакетов java.lang. * или java.util. *, чтобы упростить процедуру портирования.

В зависимости от размера кодовой базы, может быть проще переписать основную часть непосредственно, а не полагаться на инструменты. Java и C имеют большое синтаксическое сходство, но несоответствие между прямым процедурным кодом C и объектно-ориентированными функциями Java может вызвать проблемы. Автоматизированные инструменты могут генерировать практически недоступный код C при попытке обойти это, и всегда есть возможность для тонких ошибок.

2016 обновление: Не делайте этого, ни сейчас, ни когда-либо. Варианты, которые использовались для обеспечения этого, не поддерживались (например, GCJ), и, возможно, легче найти разработчика, свободно владеющего java, чем C. Кроме того, производительность Java продолжала улучшаться, и базовые реализации, как правило, имеют аналогичную производительность. Оптимизированный C все еще быстрее, но край становится все меньше и меньше с каждой версией JRE.

-121--4349462-

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

В противном случае это вопрос нормализации . Иногда допустима денормализация таблицы. Денормализация , особенно в среде, подобной хранилищу данных, может использоваться для повышения производительности. Однако важно обеспечить согласованность данных. Другими словами, необходимо убедиться, что поле total обновляется при изменении price или person .

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

Примечание: таблица не может быть 3NF (третья обычная форма) до тех пор, пока не будут удалены вычисляемые поля.

1
ответ дан 6 December 2019 в 10:50
поделиться

document.getElityStartId («divId») .innerHTML = «new content!»

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

-121--1890789-

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

С помощью этого поля очень легко ВЫБРАТЬ: SELECT price, people, (price * people) AS total FROM some_table;

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

BR

0
ответ дан 6 December 2019 в 10:50
поделиться

CSS не поддерживает эту функцию. Необходимо использовать сценарии на стороне клиента.

-121--803199-

Вы должны пойти с подрывной, или, может быть, git или mercurial.

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

Кроме того, вам, вероятно, следует получить сторонний хостинг вместо запуска собственного сервера.

-121--3227039-

Как только вы можете вычислить значение - в этом случае довольно легко - оно избыточно. Вы почти никогда не должны хранить избыточные данные. Это означает, что каждое место, где вы обновляете либо цену, либо людей, вы должны быть уверены, чтобы обновить всего. Если вы забудете сделать это даже в одном месте, данные теперь противоречивы. Предположим, у вас теперь есть запись, которая говорит, что цена = $10, люди = 3, итого = $40. Если у вас есть разные программы, отображающие информацию в разных путях - разные итоговые значения или подмножества или что-то такое - пользователь может получить разные ответы на один и тот же вопрос в зависимости от того, как он его задал. Хотя получить неправильный ответ плохо, еще хуже иногда получить правильный ответ, а иногда и неправильный ответ, потому что тогда может быть непонятно, как устранить проблему. Я имею в виду, если я вижу, что определенный клиент показывает 2 человек, когда он должен показать 3, предположительно, есть какой-то экран, на который я могу перейти, заменить 2 на 3, нажмите сохранить или что-то еще, и он исправлен. Но если там написано $10 умножить на 2 человека = $30, куда мне пойти, чтобы это исправить? Как?

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

Я работаю над системой, которая сейчас заполнена избыточными данными. Основная информация о каждом продукте нашей компании хранится в таблице « предмете». Для каждой единицы в запасе имеется запись запаса, и вместо простой ссылки на запись позиции они копируют все данные для каждой единицы запаса. При продаже предмета все данные копируются в запись продажи. Если что-то возвращается, мы копируем все данные в запись возврата. И т.д. для нескольких других типов записей. Это вызывает бесконечные неприятности. Когда-то у нас была проблема, когда пользователь выполнял запрос на поиск предметов с определенными характеристиками, а список попаданий включал предметы, которые не соответствовали критериям поиска. Почему? Поскольку запрос находит все записи предмета, удовлетворяющие критериям поиска, он пытается сопоставить эти записи предмета с записями запасов по номеру детали... но некоторые записи запасов не соответствовали записи предмета по другим критериям по различным причинам. Сейчас я работаю над устранением проблемы, когда данные о стоимости не всегда копируются из записей о запасах в записи о продажах. Я хотел бы просто переработать базу данных, чтобы исключить все избыточные данные, но это был бы огромный проект.

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

Умножение двух чисел вместе в записи, которую вы уже читаете? Ни за что. Я не могу представить, что это вызовет какие-либо проблемы с производительностью. Если компонент Database Engine не может умножить два числа в крошечном проценте времени, которое требуется для чтения записи, получите новый компонент Database Engine.

0
ответ дан 6 December 2019 в 10:50
поделиться

Если вас беспокоит производительность выбора (по крайней мере, с WHERE total = xx.xx), вы можете просто добавить индекс.

СОЗДАТЬ ИНДЕКС booking_total ПРИ бронировании ((цена * человек));

Это изменит план запроса для SELECT * из бронирования, где цена * люди = 58,2; из этого;

Seq Scan при бронировании (стоимость = 0,00..299,96 строк = 60 ширина = 24 ) (фактическое время = 0,015..2,926 строк = 1 цикл = 1) Фильтр: ((цена * (люди) :: двойная точность) = 58,2 :: двойная точность) Общее время выполнения: 2,947 мс

к этому

Сканирование кучи битовой карты при бронировании (стоимость = 4,30..20,83 строк = 5, ширина = 24) (фактическое время = 0,016..0,016 строк = 1 цикл = 1) { {1}} Повторная проверка Cond: ((цена * (люди) :: двойная точность) = 58,2 :: двойная точность) -> Сканирование растрового индекса на booking_total (стоимость = 0,00..4,29 строк = 5 ширина = 0) (фактическое время = 0,009..0,009 строк = 1 цикл = 1) Индекс Cond: ((цена * (люди) :: двойная точность) = 58,2 :: двойная точность) Итого время выполнения: 0,044 мс

PostgreSQL потрясающе: -)

1
ответ дан 6 December 2019 в 10:50
поделиться

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

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

0
ответ дан 6 December 2019 в 10:50
поделиться

Я часто выступаю за вычисляемое поле, предполагая, что вы делаете это правильно, определяя поле в базе данных как вычисленное. Таким образом, расчет всегда применим, независимо от того, как меняются данные. Я бы сделал это только в том случае, если вам нужно получить эти вычисления в отчетах, содержащих много записей. Конечно, легко написать формулу в запросе, но если вы часто вычисляете это число, вы тратите ресурсы сервера (вычисляемое поле выполняет вычисление только при изменении информации) и, возможно, серьезно замедляет запрос, если он должен выполнять вычисление для миллионов записей для отчетов. Материализованное представление также является хорошей идеей (поскольку оно будет предварительно вычисляться), но обычное представление просто избавляет вас от многократного написания вычисления, оно не дает преимущества в производительности вычисляемого поля. С другой стороны, я никогда не создаю представления, если мне это не нужно (т. Е. Я могу решить проблему другим способом), поскольку они могут привести к реальным проблемам с производительностью, когда люди начнут создавать представления поверх представлений. Не используйте молоток, если вам нужна отвертка.

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

2
ответ дан 6 December 2019 в 10:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: