How to Speed Up Updating Relationship Among Tables, After One or Both Tables Are Already Saved

Best way to handle updates for one-to-many relationship

I'd do it this way:

DELETE FROM ball_color_mapping WHERE ball_id = ? AND color_id NOT IN (?, ?, ?);

INSERT INTO ball_color_mapping VALUES (?, ?), ...
ON DUPLICATE KEY UPDATE color_id=VALUES(color_id);

That handles cases where a color is removed from the set of colors for a ball, then it inserts where necessary, and does a no-op UPDATE if the color is already in the database.

This assumes the pair of columns in ball_color_mapping is its primary key, to trigger the ON DUPLICATE clause.

Update record in many-to-many linking table

(A 'bridging table' is the usual name to support a many-to-many relationship, although there's many other names. 'Linking table' is too vague of a term: there's many ways some table might link to others.)

My current practice of updating is to delete all the old records and then insert the new records in to the linking table.

Don't do that.

I'm thinking if the best practice is actually compare two arrays

No that's not best practice. You are making this too hard.

  • If user input says Artist A has Skill S1 but the bridging table hasn't recorded that, insert it -- that is, insert a single row.
  • If user input doesn't say Artist A has Skill S2, but the bridging table does record that, delete it -- that is, delete a single row.
  • Deleting something is usually one of those actions you want to check with the user: are you sure? When they click Ok, delete the row. There's no need to think in terms of arrays or whole sets of records.

(Yes, what's held in tables is sets. But user transactions are usually row-at-a-time. In your scenario, it's not like an Artist will all-of-a-sudden learn to play the piano and juggle, and lose the ability to tap-dance. That is I'd guess, Skills are 'Slowly changing'.)

Consolidating tables with one-to-one relationships

Another factor to consider with wide table (many columns) is the effect on the RDBMS cache. Any good developer knows that you don't do 'select * from table' as it will carry unnecessary data over the network from RDBMS to client. But a similar effect can happen betwen disk and RAM and also affect the amount of space in RAM that a table requires to cache.

Most RDBMSes allocate a given volume of memory to cache data, thus reducing physical disk reads and speeding response to the user. This is Buffer Cache in Oracle or SQL Server

If you have a wide table and issue a query in the form 'select col1, col2, col3 from table' the RDBMS will load the full rows into RAM (not col1 through 3). As it does so it will age out older cached data. If your table is wide and you load 50 columns you of course require more RAM than for the same number of rows * a narrow table. This can have a noticeable impact on RDBMS performance.

Lots of wide tables, aging out other tables from cache and it is possible to see the IO stats go thorough the roof as commonly used tables age out of cache to make room for wide tables.

This factor should be added to the other advantages of normalised data and taken into consideration at table design time. In effect if you have a potentially wide table with some data that will be regularly accessed and some that will be rarely, consider multiple tables with a 1 to 1 relationship.

SQL one to one relationship vs. single table

You would normally split tables into two or more 1:1 related tables when the table gets very wide (i.e. has many columns). It is hard for programmers to have to deal with tables with too many columns. For big companies such tables can easily have more than 100 columns.

So imagine a product table. There is a selling price and maybe another price which was used for calculation and estimation only. Wouldn't it be good to have two tables, one for the real values and one for the planning phase? So a programmer would never confuse the two prices. Or take logistic settings for the product. You want to insert into the products table, but with all these logistic attributes in it, do you need to set some of these? If it were two tables, you would insert into the product table, and another programmer responsible for logistics data would care about the logistic table. No more confusion.

Another thing with many-column tables is that a full table scan is of course slower for a table with 150 columns than for a table with just half of this or less.

A last point is access rights. With separate tables you can grant different rights on the product's main table and the product's logistic table.

So all in all, it is rather rare to see 1:1 relations, but they can give a clearer view on data and even help with performance issues and data access.

EDIT: I'm taking Mike Sherrill's advice and (hopefully) clarify the thing about normalization.

Normalization is mainly about avoiding redundancy and relateded lack of consistence. The decision whether to hold data in only one table or more 1:1 related tables has nothing to do with this. You can decide to split a user table in one table for personal information like first and last name and another for his school, graduation and job. Both tables would stay in the normal form as the original table, because there is no data more or less redundant than before. The only column used twice would be the user id, but this is not redundant, because it is needed in both tables to identify a record.

So asking "Is it considered correct to normalize the settings into a separate table?" is not a valid question, because you don't normalize anything by putting data into a 1:1 related separate table.

When I should use one to one relationship?


1 to 0..1

  • The "1 to 0..1" between super and sub-classes is used as a part of "all classes in separate tables" strategy for implementing inheritance.

  • A "1 to 0..1" can be represented in a single table with "0..1" portion covered by NULL-able fields. However, if the relationship is mostly "1 to 0" with only a few "1 to 1" rows, splitting-off the "0..1" portion into a separate table might save some storage (and cache performance) benefits. Some databases are thriftier at storing NULLs than others, so a "cut-off point" where this strategy becomes viable can vary considerably.

1 to 1

  • The real "1 to 1" vertically partitions the data, which may have implications for caching. Databases typically implement caches at the page level, not at the level of individual fields, so even if you select only a few fields from a row, typically the whole page that row belongs to will be cached. If a row is very wide and the selected fields relatively narrow, you'll end-up caching a lot of information you don't actually need. In a situation like that, it may be useful to vertically partition the data, so only the narrower, more frequently used portion or rows gets cached, so more of them can fit into the cache, making the cache effectively "larger".

  • Another use of vertical partitioning is to change the locking behavior: databases typically cannot lock at the level of individual fields, only the whole rows. By splitting the row, you are allowing a lock to take place on only one of its halfs.

  • Triggers are also typically table-specific. While you can theoretically have just one table and have the trigger ignore the "wrong half" of the row, some databases may impose additional limits on what a trigger can and cannot do that could make this impractical. For example, Oracle doesn't let you modify the mutating table - by having separate tables, only one of them may be mutating so you can still modify the other one from your trigger.

  • Separate tables may allow more granular security.

These considerations are irrelevant in most cases, so in most cases you should consider merging the "1 to 1" tables into a single table.

See also: Why use a 1-to-1 relationship in database design?

What is the use of multiple tables with 1 to 1 relationship

There are two kinds of database analysis methods.
The first form is one that simplifies the schema in the case of the table used, employees and address it should merge.
The other method is called the third form, it consists in making the tables as independent as possible. In the case of the table employees and address it should be separated. There is no right or wrong method it is a choice to make.
However, if the database contains many tables, it is more sensible to simplify and get to the first form, but there is no obligation.

how to properly save into coredata one to many relationship

You need to use the provided method to add a "many object" in the one to many object. In your case it is called addRoutineObject:

Try this new save method:

- (void) save {

Routine *newRoutine = [NSEntityDescription insertNewObjectForEntityForName:@"Routine" inManagedObjectContext:context];
newRoutine.routineName = @"myRoutine Test Name";

NSEntityDescription *entityDesc = [NSEntityDescription entityForName:@"User" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];


NSArray *matches;
NSError *error = nil;
if (_appDelegate.isFB)
{
request.predicate = [NSPredicate predicateWithFormat:@"idFB LIKE %@",_appDelegate.fdID];
matches = [[context executeFetchRequest:request error:&error] mutableCopy];

} else
{
NSLog(@"CreateRoutinePOPUP NON FB TO BE TESTED");
request.predicate = [NSPredicate predicateWithFormat:@"email LIKE %@",_appDelegate.currentUser];
matches = [[context executeFetchRequest:request error:&error] mutableCopy];
}

if (matches.count == 0)
{
NSLog(@"no user matched");
}
else
{
User *aUser = [matches objectAtIndex:0];
[aUser addRoutineObject:newRoutine];
if (![context save:&error])
{
NSLog(@"couldn't save: %@", [error localizedDescription]);
}
}
}


Related Topics



Leave a reply



Submit