3

Recently come across an unusual scenario while normalizing an old relational database.

The Facts

There's ~8 tables linked to a central table, where references between the numerous tables may or may not exist.

There's a lot of data used, and while this table was initially designed, created and mutated over time, performance was taken into account. Thus, there were no linking tables made between the central & other tables.

I'm looking to improve the structure of this, but not sacrifice query performance, since information from all of the tables can be used for reporting.

Question: How would one go about optimizing/normalizing a table structure like the one mentioned, without sacrificing the performance factor?

I've considered the following options:

1: Adding linking tables between them would make queries quite advanced, where if a lookup is done, all of the pivot tables would need to be searched to identify any relations between them.

2: Adding the central table id as an index on the outer tables. This is an idea, but then again, to find any information, you'd need to query the other tables. To maybe improve on this, adding a type field of some kind on the central table entry would assist to identify the information that exists on the outer tables.

Edit - ERD Example

enter image description here

As an example, consider a computer repair store. For the purposes of the example, the following assumptions are made:

  • This is a small sub-system, a customer could have come in to buy an RGB fan, and didn't bring a device in. Thus, Customers don't have to have a CustomerDevice
  • When a Repair is done, and a RepairActivity is recorded, the customer could bring it back in because of whatever reason.
  • For every RepairActivity, a 1 to 1 relationship can be seen between the WorkInformation table.
  • A RepairInvoice is only generated when the customer comes into the store, thus, a RepairActivity can exist without one.
  • A Customer may have a CustomerDevice registered on the system, and not have brought it in for a repair.

Now this is a basic example, and the system mentioned in the question has many more tables attached.

  • 1
    What you call "linking tables" are only necessary when the relationship is M:N. 1:M relationships don't need such an intermediate table. Also, could you add an ER diagram, however crude, in order to better visualize the current design? No need to show columns, just tables and relationships. Sometimes "other tables", "central tables", "outer tables", is vague enough to hinder proper understading. – Tulains Córdova Mar 9 '17 at 14:13
  • 1
    What exactly do you mean by "improve the structure"? It sounds like the app is working and doesn't have performance problems. – Dan Pichelman Mar 9 '17 at 14:30
  • @TulainsCórdova I added an ERD example with a few tables for your understanding – jarodsmk Mar 10 '17 at 6:47
  • @DanPichelman The app is being rewritten to account for a wider 'audiience' of customers if you will, and thus the database needs to be looked at. Came across some tables & we're thinking of updating them, the main issue being this table that is linked to a sparse variety of others – jarodsmk Mar 10 '17 at 6:48
  • What does "WorkInformation" hold? It s a log? – Tulains Córdova Mar 10 '17 at 9:41
1

Great first question and welcome.

Short answer:

Make shure every tables has a PK, that theres is a FK for every relationship and to add indexes on columns that will be queried often, and create views that abstract you from the joins if you don't want to said joins every time. Performance will be good. RDBMS are optimized to do exactly that.

Long answer including some observations bases on limited information:

  1. WORK_INFORMATION and REPAIR_ACTIVITY having a 1:1 relationship, they have a high change of being the same entity. One possible exceptions is if WORK_INFORMATION has columns that do not apply to all REPAIR_ACTIVITYs, but, given the relationship is 1:1, I would considered whether or not they should be two separate tables. Also, 1:1 relationships are possible conceptually but not physically since you cannot insert in either table until a matching wor exists in the other... unless you are enforcing the integrity fully in code and not using database constraints.

  2. "Adding the central table id as an index on the outer tables." First, I will assume that what you call "central table" is REPAIR_ACTIVITY. Well,those tables that have a relationship with REPAIR_ACTIVITY where REPAIR_ACTIVITY is on the one side of the relationship, should already have the PK of REPAIR_ACTIVITY as a column, i.e. a foreign key pointing to REPAIR_ACTIVITY, and all FKs are indexed. The tables that have a relationship with REPAIR_ACTIVITY where REPAIR_ACTIVITY is on the many side of the relationship shouldn't have a column with the REPAIR_ACTIVITY id. That would be physically impossible since there can be only one value on any row in the one side, making the relationship 1:1.

  3. I would check the relationship between REPAIR_INVOICE and REPAIR_ACTIVITY. Is the relationship inverted (meaning REPAIR_INVOICE should be the one and REPAIR_ACTIVITY the many)? If not, disregard this suggestion and chalk it out to lack of information.

  4. "...adding a type field of some kind on the central table entry would assist to identify the information that exists on the outer tables" That is in some cases unnecessary and in other cases impossible, if what worries you is complexity of queries do this: create views where you already join the tables. Then in your code you query those views. Thay way you will not have to write the joins every time, just the WHERE part to filter the selection.

  5. Regarding performance, adding join tables where they are needed, shouldn't harm performance if all tables have a PK, there is a FK for every relationship and there are indexes on those columnes that will be queried often (PKs and FKs already have indexes).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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