База данных как файловый формат - PullRequest
3 голосов
/ 04 февраля 2009

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

Пара вопросов:
Это на самом деле не использует тот факт, что все таблицы данных имеют одинаковый формат - нет понятия «массив таблиц», это что-нибудь значит?

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

edit: Причиной для многих таблиц, по одной на серию, является то, что в каждой из них может быть от 10 до 100 прогонов с тысячами измерений. Если я хочу отобразить / запросить / удалить только один прогон, мне кажется более естественным иметь каждый из них в отдельной таблице.
Похоже, что это мышление программиста (все должно быть коллекциями отдельных объектов), который, по-видимому, предпочитает подход базы данных - хранить все вместе и использовать индексы / перекрестные ссылки.

Ответы [ 8 ]

7 голосов
/ 04 февраля 2009

У вас будет одна таблица (Run), в которой хранятся дата / время / местоположение, и целочисленный первичный ключ (автоинкремент).

У вас будет другая таблица (Измерения), в которой хранятся время / напряжение / ток / температура, целочисленный первичный ключ (автоинкремент) и FK для выполнения (просто столбец с ненулевым целым числом, называемый RunID).

Итого 2 таблицы.

2 голосов
/ 04 февраля 2009

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

Исходное предположение: вы захотите по крайней мере иметь таблицу метаданных для хранения метаданных эксперимента и одну или несколько таблиц для хранения измерений.

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

Metadata
----------
experimentName
experimentLocation
experimentDateTime
...
measurementTableName

И таблица для каждого эксперимента, каждый из которых выглядит одинаково:

Measurement0001    Measurement0002    Measurement0003    Measurementt0004 
--------------     --------------     --------------     -------------- 
measurementNum     measurementNum     measurementNum     measurementNum 
voltage            voltage            voltage            voltage        
amps               amps               amps               amps           

Затем в вашей программе вам сначала нужно получить метаданные:

select * from Metadata where experimentName='Johnson Controls 1'

, который, помимо прочего, будет возвращать measureTableName для интересующего эксперимента (скажем, Measurement0002). Тогда ваш следующий запрос:

select * from Measurement0002 order by measurementNum

Теперь давайте возьмем подход «сохранить все данные в таблице измерений». Ваша таблица метаданных будет выглядеть так:

Metadata
----------
experimentName
experimentLocation
experimentDateTime
...
measurementSetID

И таблица для всех экспериментов.

Measurement
--------------
measurementSetID
measurementNum
voltage            
amps               

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

select * from Metadata where experimentName='Johnson Controls 1'

, который, помимо прочего, даст вам MeasureSetID, который вы будете использовать для получения только измерений из желаемого набора (скажем, id = 2). Тогда ваш следующий запрос:

select * from Measurement where measurementSetID=2 order by measurementNum

Итак, давайте сравним два подхода ... Запросы метаданных по существу идентичны. Единственное отличие состоит в том, что в первом случае вы извлекаете measureTableName для желаемой экспериментальной таблицы; в то время как во втором случае вы извлекаете measureSetId для нужных записей в таблице измерений.

Запросы на выборку измерений также практически одинаковы:

select * from Measurement0002                      order by measurementNum
select * from Measurement where measurementSetID=2 order by measurementNum

Единственной переменной является либо имя таблицы, либо measureSetID:

select * from <tablename>                                order by measurementNum
select * from Measurement where measurementSetID=<setID> order by measurementNum

Результат запроса почти тот же, второй подход просто даст вам дополнительный столбец в ваших данных (measureSetID), который вы можете игнорировать, потому что все возвращаемые строки будут иметь одинаковый идентификатор набора.

2 голосов
/ 04 февраля 2009

Я бы сделал следующее (спасибо Гранту за оформление стола):

+-------------------+     +----------------------+
|    Sequence       |     | Measurements         |     +------------------+
+-------------------+     +----------------------+     | Measurement Type |
|  metaID (pri Key) |---->| metaID               |     +------------------+
|  location         |     | typeID               |---->| typeID (pri Key) |
|  other metadata   |     | measureID   (pri Key)|     | typeName         |
+-------------------+     | value                |     | typeUnits        |
                          +----------------------+     +------------------+

Таким образом, таблица типов будет иметь:

typeID      typeName     typeUnits
0           Volts        V
1           Current      A

Таблица измерений будет иметь одну строку для каждого измерения.

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

Это позволит вам легко выполнить один тестовый запуск с вольтами и током, а другой - с тестами вольт1, вольт2, током, сопротивлением без изменения таблицы и всех запросов, которые с ней идут.

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

Ну, на самом деле это не так просто, потому что в какой-то момент вам нужно решить, какую таблицу вы хотите просмотреть, и вставить это имя таблицы в оператор SQL. Их так же легко поместить в одну таблицу, и вместо того, чтобы помещать имя таблицы в запрос SQL, поместите имя последовательности в виде WHERE sequence = "sequencenumber". Это так же просто и не должно быть медленнее, даже с тысячами записей. На некоторых SQL-серверах вы также можете создавать представления, которые похожи на «фальшивые» таблицы. Она выглядит как таблица, но на самом деле это встроенный оператор SQL - вы можете создать новое представление для каждой последовательности, если хотите, и затем можете манипулировать ими, как если бы они были их собственной таблицей.

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

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

-Adam

2 голосов
/ 04 февраля 2009

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

Вы заявляете, однако, что это вопрос о дизайне базы данных, и правильный дизайн действительно использует эти две таблицы. Разделение данных - это то, что вы сделаете позже, если это будет абсолютно необходимо, и, скорее всего, когда вы пройдете эти n x 100 запусков x m x 1000 измерений.

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

0 голосов
/ 04 февраля 2009

Говоря в целом, подход с двумя таблицами представляется наиболее подходящим для вашего приложения.

Чтобы обеспечить хорошую производительность, убедитесь, что вы создаете индексы для своих таблиц. Например, для схемы Гранта вам понадобится индекс в таблице измерений с ключами metaID (первичный ключ) и measureID (вторичный ключ).

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

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

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

0 голосов
/ 04 февраля 2009

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

+-------------------+     +----------------------+
|    Meta Data      |     | Measurements         |
+-------------------+     +----------------------+
|  metaID (pri Key) |---->| metaID <-(index this)| 
|  location         |     | measureID   (pri Key)|
|  metaDate         |     | voltage              |
+-------------------+     | amperes              |
                          | current              |
                          +----------------------+

У вас будет куча записей измерений с одним и тем же мета-идентификатором (но у них будет свой собственный идентификатор), и они будут соответствовать метаданным.

0 голосов
/ 04 февраля 2009

Если я понимаю ваш вопрос, я бы, вероятно, использовал две таблицы.

TestInfo. Каждая запись содержит дату и т. Д., Когда был проведен тест. Это ваши метаданные. Кроме того, я бы добавил сгенерированный RunId, который является уникальным числом.

'RunInfo' Каждая запись содержит идентификатор runId и информацию о токе, температуре, времени и т. Д.

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

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

0 голосов
/ 04 февраля 2009

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

Если они не связаны, лучше просто иметь значение и индикатор типа значения (1 = напряжение, 2 = ток и т. Д.).

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

Ради аргумента давайте предположим, что ваши метаданные - это просто местоположение. Вы должны настроить таблицу местоположений, а затем поместить соответствующий locationID в поле метаданных. (убедитесь, что введите INT, если вы вводите locationId, чтобы вы могли позже присоединиться к таблицам)

Обычно вы используете справочную таблицу для индикаторов типов и используете представление для создания портов, соединяя эти поля.

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