lundi 22 mai 2017

Best practice to get 1:n database relations into code

Imagine a database with two tables like this:

persons
---------
|pid|name|
|  0| Tom|
|  1|Hans|
|  2| Ken|
---------

cars
---------------
|cid|pid|  car|
|  0|  1|  BMW|
|  1|  1| Audi|
|  2|  2| Benz|
---------------

A 1:n relation between persons and cars.

What is the best practice to associate these in code?

Let's assume I'd like to fill this simple class:

class Person {
  string name;
  List<string> cars;
}

From the top of my head I could go three ways:

Way 1:

Do two queries separately and do a nested foreach to associate all cars.

Two SQL Queries:

SELECT * FROM persons;
SELECT * FROM cars;

With the simplistic pseudo code:

List<Person> personList;
foreach(row in personQuery) {
  person = new Person(personQuery.name);
  foreach(row in carQuery)
    if(carQuery.pid == personQuery.pid)
      person.AddCar(carQuery.car);
}

Way 2:

Do one query with a join and ignore duplicate information.

One SQL Query:

 SELECT * FROM persons JOIN cars ON persons.pid = cars.pid;

With:

List<Person> personList;
int lastID;
foreach(row in Query) {
  if(Query.pid != lastID) {
    person = new Person(personQuery.name);
    personList.Add(person);
  }
  person.AddCar(Query.car);
}

Way 3:

Do one query to get all persons and then one for each person to get the associated cars.

Many SQL Queries:

SELECT * FROM persons;
SELECT * FROM cars WHERE pid = @param;

With:

List<Person> personList;
foreach(row in personQuery) {
  person = new Person(personQuery.name);
  carQuery = DoCarQuery(personQuery.pid);
  foreach(row in carQuery)
    person.AddCar(carQuery.car);
  personList.Add(person);
}

In my testing it seems like the first way is the fastest, but it degrades really fast because it's a n^m approach and it gets even slower if I have multiple 1:n relations like a third table with "bikes" in the example above.

I encounter this problem regularly in my work and couldn't find a best practice only, though this could be because I couldn't word the problem accurately, because I only found matches on how to make 1:n databases in the first place :/

Aucun commentaire:

Enregistrer un commentaire