2

I'm creating a database of simulation results, and am trying to do so the right way. I've attempted to show relationships between data to make sure nothing redundant is thrown in.

My current structure is like this:

Experiment

Primary key: SimulationID

Tables:

  • measurement
  • sampling_rate
  • first_draft_flow_rate
  • second_draft_flow_rate
  • final_flow_rate

Foreign key relating these tables: cycle_count

Each table contains the primary key, foreign key, and values for the variables.

So for a given experiment, it runs for so many cycles (the number of cycles it runs for varies from simulation to simulation). We log data at each cycle of the simulation.

I've made a table called measurement, sampling_rate, etc, but am not sure what to name the columns. Should the also be called measurement, sampling_rate, etc? Or should I just use Value as the column name?

Here's a spreadsheet with a sample log to demonstrate what I'm working with. All of this data would be filed under a single SimulationID.

spreadsheet

Also, any tips on how best to design a DB to be normal/best practices would be greatly appreciated.

2

3 Answers 3

2

This is not database administration, this is data modeling. Very different disciplines.

I'm guessing your main entity is Simulation and the tables you list describe it. You don't show the structure or content of these tables so the following is based on conjecture.

Measurement looks like it could be a list of measurement types: temperature, flow, particles per unit volume, etc. SamplingRates also looks like a list of valid rates: 1/sec, 10/sec, 100/sec, etc.

Finally there are three table that look like they should be one, FlowRates, that is also a lookup table.

This would mean a Simulation is the recorded results of, say, a temperature reading at a rate of 10 times per second of a 30 ml/sec flow.

Is that accurate? If so, here would be an example:

Measurements
 ID  Name
  1  Temperature
  2  Particles per ml

SamplingRates
 ID  Name  Period
  1     1     sec
  2    10     sec

FlowRates
 ID  Rate  Unit Period
  1    10    ML    sec
  2    20    ML    sec
  2    30    ML    sec

So the example Simulation entry would show a Measurement of 1, SamplingRate of 2 and FlowRate of 3 -- along with the results of the measurement, of course, and probably a timestamp of when the simulation was performed.

It would help a lot if you would give a plain language description of an experiment: "An experiment consists of any number of simulations. A simulation is made up of various readings of...made at a certain frequency based on ..." Don't think in terms of tables and columns. Pretend you're talking to a lab technician.

Update: When designing a table (and this pertains to naming the fields) it is generally a good idea to isolate the entity from all other entities -- that is, the naming should be done as context-free as possible. What that means is if you have a field that represents, say, the name or description of the entity, then by all means call those fields "Name" and "Description". No matter that you have dozens of other fields with identical names in tables scattered around the database.

A table has no context. It is the query that establishes a context.

select  s.Name as NewSite, u1.Name as Owner, u2.Name as Manager
from    Site s
join    Users u1
    on  u1.ID = s.OwnerID
join    Users u1
    on  u2.ID = s.MgrID
where   s.Created > '2015-01-01';

Here are three tables each with the field Name -- it really doesn't matter that one table is used twice. Within each table, Name means "this is the name of the entity represented by this row."

The context established by this query is easily identified. It is looking at the owner and manager of all newly created sites and renames each Name field to suit the context. Different queries can and do use the fields in completely different contexts. As it is the query which sets the context, let the query rename the fields to whatever best suits that context.

Don't try to force a context with a table by naming the fields User_ID or User_Name and so forth. In a query, fields should be prefixed with the table name or alias anyway, so there's never any confusion.

where  User.Name = 'John Smith'

Compare with

where  User.User_Name = 'John Smith'

The extra "User_" adds no useful information. Besides, you're bound to hit something like this:

where ExtremelyLongTableName.ExtremelyLongTableName_SomewhatLongFieldName = ...

I'm exhausted just typing it the one time. Besides, some DBMSs limit the length of object names. Oracle, iirc, only considers the first 32 characters of an object name. I've hit that limit more than once in shops that use the tablename_fieldname convention. At that point you have to use abbreviations which is really messy.

Anyway, "best practices" is a fairly subjective concept. Opinions will vary. Choose what is most comfortable for you.

4
  • 1
    Sorry for the vagueness. The simulation is of the native human glucose system. I'm working on a controller for this system that makes use of two substances: Insulin (brings glucose down) and Dextrose (brings glucose up). Measurements are taken every 10 minutes, unless the system is very unstable, in which case a "5 minute mode" will be triggered. The controller flows have three stages they go through. Rough control is determined at *fn (eg INSfn), more minute control is *fn2c, and final control is given as *fn3c. This value is then capped off at safe physiological levels. (continued) Sep 30, 2015 at 19:00
  • 1
    To make these decisions, I keep track of three values: Xa (current glucose value), Xb (glucose value from the last cycle, which is 5 or 10 minute ago), and Xc. Using these values, I determine if the next cycle is going to be a "5 min clock?", then push the current and past values into the controllers. Finally, there's a "bolus controller" which handles rapid changes of the system much better than the other controllers. The fn3c is added to ' bolus' to quickly adjust rapidly rising or falling values. The remembered value *fp consists only of *fn3c_cap, and not the bolus. (continued) Sep 30, 2015 at 19:04
  • 1
    All of these flow rates are in mL/hr, adjusted according to the concentration of the solution you're using. Xa,b,c are in mg/dL. I also keep track of the conditions that cause a controller to do what it does in a "rule number". So each controller has a rule number for both insulin and dextrose. I've kind of got a DB layout planned after all of the discussion over here. See here: pastebin.com/eRUTv4sS Hopefully that clears things up a bit. Sep 30, 2015 at 19:11
  • OK, now we've gone from trickle to flood and gotten far from the original question. My fault. I got diverted. I'll edit my answer to try to get us back on track.
    – TommCatt
    Sep 30, 2015 at 19:35
2

My preference would be to name the columns like final_flow_rate__value, etc, since value by itself can easily become very confusing if there are multiple columns named that.

Take for instance:

SELECT 
    measurement.value
    sampling_rate.value
    first_draft_flow_rate.value
    second_draft_flow_rate.value
    final_flow_rate.value
FROM 
    measurement
    INNER JOIN sampling_rate ON ...
    INNER JOIN first_draft_flow_rate ON ...
    INNER JOIN second_draft_flow_rate ON ...
    INNER JOIN final_flow_rate ON ...

Results will show column headings all saying just value.

The following returns column headers that make more sense.:

SELECT 
    measurement.measurement_value
    sampling_rate.sampling_rate_value
    first_draft_flow_rate.first_draft_flow_rate_value
    second_draft_flow_rate.second_draft_flow_rate_value
    final_flow_rate.final_flow_rate_value
FROM 
    measurement
    INNER JOIN sampling_rate ON ...
    INNER JOIN first_draft_flow_rate ON ...
    INNER JOIN second_draft_flow_rate ON ...
    INNER JOIN final_flow_rate ON ...

As a DBA charged with debugging other-people's-code, I especially hate it when every surrogate key in a database is named ID in the referenced table, and xxx_ID in the referencing table. For instance:

CREATE TABLE dbo.SomeTable
(
    ID INT NOT NULL
        CONSTRAINT PK_SomeTable
        PRIMARY KEY CLUSTERED
    , ...
);

CREATE TABLE dbo.SomeOtherTable
(
    ID INT NOT NULL
        CONSTRAINT PK_SomeOtherTable
        PRIMARY KEY CLUSTERED
    , SomeTable_ID INT NOT NULL
        CONSTRAINT FK_SomeOtherTable_SomeTable
        FOREIGN KEY REFERENCES dbo.SomeTable(ID)
    , ...
);

This pattern leads to hard-to-debug patterns such as:

SELECT SomeTableID = st.ID
    , SomeOtherTableID = sot.ID
FROM dbo.SomeTable st
    INNER JOIN dbo.SomeOtherTable sot ON st.ID = sot.ID;

Which should in fact be:

SELECT SomeTableID = st.ID
    , SomeOtherTableID = sot.ID
FROM dbo.SomeTable st
    INNER JOIN dbo.SomeOtherTable sot ON st.ID = sot.SomeTable_ID;

If the tables are defined as:

CREATE TABLE dbo.SomeTable
(
    SomeTable_ID INT NOT NULL
        CONSTRAINT PK_SomeTable
        PRIMARY KEY CLUSTERED
    , ...
);

CREATE TABLE dbo.SomeOtherTable
(
    SomeOtherTable_ID INT NOT NULL
        CONSTRAINT PK_SomeOtherTable
        PRIMARY KEY CLUSTERED
    , SomeTable_ID INT NOT NULL
        CONSTRAINT FK_SomeOtherTable_SomeTable
        FOREIGN KEY REFERENCES dbo.SomeTable(SomeTable_ID)
    , ...
);

With the same names across tables, this bug will almost NEVER occur, since the "wrong" version would be obvious to spot if implemented, and likely would never be implemented wrongly in the first place:

SELECT st.SomeTable_ID
    , sot.SomeOtherTable_ID
FROM dbo.SomeTable st
    INNER JOIN dbo.SomeOtherTable sot ON st.SomeTable_ID = sot.SomeOtherTable_ID;

The correct version, which is immensely more readable, is:

SELECT st.SomeTable_ID
    , sot.SomeOtherTable_ID
FROM dbo.SomeTable st
    INNER JOIN dbo.SomeOtherTable sot ON st.SomeTable_ID = sot.SomeTable_ID;

Columns that contain the same content across tables should be named precisely the same in every table they are defined in, if only for the sake of reducing negative legacy.

1
  • 1
    Excellent examples of why [ID] is a horrible field name. Aug 30, 2016 at 19:47
1

Always try to think ahead, use table and field names that are self documenting (self-explanatory) whenever possible. Don't just string a bunch of letters together and assume the person to come behind you would have any idea what they're looking at. Naming things in this matter also makes it much easier to see what results your query is returning.

5
  • 1
    This is my first ever foray into database administration, so I worry a lot about just this. Things that may make sense to me would be complete gibberish to an onlooker. That's why I'm looking to nail down best practices before ever starting the project. Sep 29, 2015 at 20:40
  • Naming conventions can vary from place to place. So when you're looking into something like this, try and think about it from the perspective of an end user. I just know that in all the code/SQL I've ever had to deal with that when the variables, functions, procedures, etc are self describing it makes everything easier to read and to see what is going on. Sep 29, 2015 at 21:13
  • 1
    Naming conventions can vary from place to place. So when you're looking into something like this, try and think about it from the perspective of an end user. I just know that in all the code/SQL I've ever had to deal with that when the variables, functions, procedures, etc are self describing it makes everything easier to read and to see what is going on. For instance I work with a database that has great swaths of nearly data model-less aspects. There is one table that has one primary key and what could qualify as about 10 other candidate/foreign keys. They're generally of the for xxxID Sep 29, 2015 at 21:21
  • 2
    And of those field names, there are several that are xxyID, xxzID, xxwID. If instead of using all sorts of shortcut naming conventions that don't make any sense to me, the original designer had used self documenting naming practices and put a bit more effort in my job would be much easier. Just think about someone else reading your SQL, better yet find a friend that understands it and have them look it over. If they can get a pretty good idea of what is going on and what everything means I'd say you'd be headed in the right direction. Sep 29, 2015 at 21:24
  • 1
    In years gone by, some enterprises undertook to compile a "data dictionary" to make sense of all the data elements being manipulated and shared between business processes. This was basically a lexicon of data elements with detailed definitions, from a business perspective. It's a huge undertaking. There is a miniature data dictionary inside the system tables of all major database systems. You can use this to help document your data, assuming the next person looks there. Sep 30, 2015 at 7:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.