Le pub des programmeurs
- 1 927 réponses
- 117 participants
- 124 530 vues
- 130 followers

Anonyme
521410

Sujet de la discussion Posté le 25/08/2005 à 17:21:03Le pub des programmeurs
Salut
y a des programeurs sur AF si oui vous bossez sous quoi ?


Anonyme
4548

1881 Posté le 21/02/2020 à 12:27:28
Ha non l'index a 4 colonnes je suis d'accord c'est pas beau, là c'est sans doute plus un problème de besoin pas bien identifié comme a souligné Krisfrom.

Truelle est un manchot
10420

Drogué·e à l’AFéine
Membre depuis 14 ans
1882 Posté le 21/02/2020 à 14:04:56
Citation de krisfrom78 :
Perso, identifier ton besoins en partant direct sur les CREATE TABLE ça me semble un peu compliqué.
Avant de modéliser, et pour notre (en tout cas la mienne) compréhension de ton objectif, je pense qu'il faudrait commencer par poser quelques questions basiques en mode texte du type :
- Un client peut-il avoir plusieurs fournisseurs ?
- Un fournisseur peut-il avoir plusieurs clients ?
- Un fournisseur à t'il plusieurs adresses ?
- etc...
ça permet d'identifier les relations 1,1 / 1,N / N,N pour ensuite construire un modèle relationnel...
- Une personne peut être ami avec plusieurs personnes.
Du coup je voyais le truc comme ca: A est ami avec B = Une relation (A, B) + relation inverse (B, A) et les informations de cette relation stockées dans une autre table.

Dr Pouet
52037

Membre d’honneur
Membre depuis 20 ans
1883 Posté le 21/02/2020 à 14:09:59
Oui là tu as deux tables : personne, relation.
Avec : relation(A,B) = relation(B,A)
Avec : relation(A,B) = relation(B,A)

Truelle est un manchot
10420

Drogué·e à l’AFéine
Membre depuis 14 ans
1884 Posté le 21/02/2020 à 14:34:48
Après l'index a 4 colonnes je sais pas pourquoi j'ai fait ca, j'imaginais qu'il fallait faire en sorte qu'une `relationship_infos` soit bien lié à deux autre `relationship`.
Mais si un id suffit alors ca me va. Je ne connais pas bien les bonne pratiques en fait.
Pour la relation inverse je me basais sur différents posts sur dba.stackexchange et sur ce post notamment sur Quora:
Après j'ai aussi vu ce post qui a une approche différente: https://www.alibabacloud.com/blog/social-friend-relationship-system-practice-in-postgresql---accelerating-queries-of-positive-and-negative-relationships_595043
Mais si un id suffit alors ca me va. Je ne connais pas bien les bonne pratiques en fait.
Pour la relation inverse je me basais sur différents posts sur dba.stackexchange et sur ce post notamment sur Quora:
Citation :
How does Facebook maintain a list of friends for each user? Does it maintain a separate table for each user?
Citation :
I work in Serwis społecznościowy nk.pl - platforma komunikacji dla wszystkich internautów - nk.pl which used to be the largest social network in Poland, and I can tell you one thing: such relations need to be stored "in both ways". Others have suggested here, that you can use a single table `friendship` with two columns `user_a`, `user_b` and maintain single row for each frendship. This is a very bad idea for scalability and simplicity of code. As you can see in Marcus Matos answer it quickly leads to massive UNIONS and complicated "ifology" in JOINs as each edge must be double checked in both directions. Moreover this makes sharding (spliting the database across many machines) almost impossible.
What we do instead is add two edges: for example if user #17 adds user #36 to her friends list, we perform two INSERTs for (17,36) and (36,17).
This way list of friends of a single user can be retrieved with a single, simple select.
Also, we shard the database using `shard_number=user_a MOD number_of_shards` which lets us retrieve whole friends list in a single query to a single machine.
It also makes "friends-of-friends" and "common-friends" problems a bit easier, but frankly, even Serwis społecznościowy nk.pl - platforma komunikacji dla wszystkich internautów - nk.pl has more than 4 bilion edges, and handling this in real time is a bit tricky, so we actually have batch jobs which run at night, so that propositions of people you might know are cached and available in the morning.
To make my point more convincing: we've actually used the approach with single friendship = single row, for two years IIRC, and it was a mess!
One more thing: you can make sure that you always perform the two INSERTs in the same order you perform two DELETEs (for example by using lexicographic ordering) and then if there is some integrity problem (one database has a row, but the symmetric row is missing) you can easily tell what was the last operation that failed and restore the consistent state.
For example if you see that there is (36,17) row, but (17,36) is missing, then it must mean, that there was DELETE (17,36), DELETE (36,17) transaction which failed in the middle.
Après j'ai aussi vu ce post qui a une approche différente: https://www.alibabacloud.com/blog/social-friend-relationship-system-practice-in-postgresql---accelerating-queries-of-positive-and-negative-relationships_595043
[ Dernière édition du message le 21/02/2020 à 14:44:33 ]

miles1981
8363

Je poste, donc je suis
Membre depuis 20 ans
1885 Posté le 21/02/2020 à 14:54:50
Perso, pou rce genre de choses, je passe en NoSql et je stocke une liste de chaque cote avec les connexions. Tant que tu n'as pas des milliers de liens, ca peut passer.
Audio Toolkit: http://www.audio-tk.com/

deozza
13387

Drogué·e à l’AFéine
Membre depuis 11 ans
1886 Posté le 21/02/2020 à 15:09:39
Qu'est-ce que ca apporte en vrai, le nosql par rapport a un sgbdr ? J'ai encore du mal a m'en rendre compte
Pour mon app je suis passe de mysql a mongodb. Parce que je traite que des donnees en json et que mongodb enregistre littéralement en json et que j'ai besoin de rajouter a la volée de nouvelles propriétés sans me prendre la tête avec des migrations. Mais aussi parce que c'est hype, mongodb.
Pour mon app je suis passe de mysql a mongodb. Parce que je traite que des donnees en json et que mongodb enregistre littéralement en json et que j'ai besoin de rajouter a la volée de nouvelles propriétés sans me prendre la tête avec des migrations. Mais aussi parce que c'est hype, mongodb.
Le chien aboie mais n'invente pas le fil à décongeler le beurre.
Les 6l6, des lampes qui nous éclairaient

Truelle est un manchot
10420

Drogué·e à l’AFéine
Membre depuis 14 ans
1887 Posté le 21/02/2020 à 15:17:30
Citation de miles1981 :
Perso, pou rce genre de choses, je passe en NoSql et je stocke une liste de chaque cote avec les connexions. Tant que tu n'as pas des milliers de liens, ca peut passer.
Oui mais tu dois bien stocker les informations sur ces connexions quelque part?

Dr Pouet
52037

Membre d’honneur
Membre depuis 20 ans
1888 Posté le 21/02/2020 à 15:31:34
Citation :
Others have suggested here, that you can use a single table `friendship` with two columns `user_a`, `user_b` and maintain single row for each frendship. This is a very bad idea for scalability and simplicity of code.
Effectivement, la bonne solution n’est pas forcément la même pour mille personnes ou plus d’un million.

Truelle est un manchot
10420

Drogué·e à l’AFéine
Membre depuis 14 ans
1889 Posté le 21/02/2020 à 16:16:05
Après quelques petites recherche en me basant sur le post du blog aliabacloud, je suis arrivé à un truc complètement différent:
On a deux tables:
- "account" avec l'id du compte plus un array d'entier contenant la liste d'id des amis "friends_id"
- "relationships_informations" pour les infos d'une relation entre X et Y, avec un id et un array d'entier pour stocker les id des deux account qui sont copaing.
- On créé un index sur le tableau d'entier.
Exemple:
On a Deux comptes: A et B
A devient ami avec B.
Donc on ajoute B dans la liste d'amis de A: "account(id=A, friends_id=(A.friends_id + B))"
Puis on ajoute A dans la liste d'amis de B: "account(id=B, friends_id=(B.friends_id + A))"
Enfin on crée une "relationships_info": "relationships_informations(id, uids=int[A.id, B.id], foo=bar, baz=spam)" Avec un array d'entier contenant l'id des deux accounts + toutes les données sur la relation.
Conclusion:
Du coup j'ai plus de tables relation + relation inversé.
Pour récupérer les listes d'amis:
- Je peux facilement récupérer la liste de mes amis.
- Ou la liste des amis de mes amis en concaténant ces listes puis en faisant un uniq(sort(liste_damis_de_mes_amis)), idem pour amis des amis de mes amis et ainsi de suite.
Pour récupérer les infos sur les relations:
- Pour une relation il me suffit de faire un select et de vérifier que la colonne "uids" contient bien mes deux ids.
- Pour plusieurs relations avec l'id d'une personne je peux faire un select dans la table "relationships_infos" sur la colonne "uids" en vérifiant qu'elle contient bien mon id.
- Idem avec l'id de plusieurs personnes en utilisant un "ANY" ou un truc du genre(je ne sais pas si ca existe en SQL).
Après je ne sais pas si je peux créer un type d'array qui doit contenir obligatoirement deux entier différents.
Ce qui éviterait que des données foireuse soient rentrées genre un array de 0,1,3 ou plus d'items.
J'ai vu qu'on pouvait faire un "CREATE UNIQUE INDEX" mais j'imagine que sur une colonne de type array ca doit pas être possible.
Après j'imagine qu'il vaut mieux faire un sort() de chaque array avant enregistrement, pour éviter les doublons du type [1,2], [2,1].
Peut-être qu'un autre type serait envisageable sur la table relationships_infos, je sais pas.
CREATE TABLE account(
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
friends_id INTEGER[]
);
CREATE TABLE relationships_informations(
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
uids INTEGER[]
);
CREATE INDEX users_id ON relationships_informations USING GIN (uids);
On a deux tables:
- "account" avec l'id du compte plus un array d'entier contenant la liste d'id des amis "friends_id"
- "relationships_informations" pour les infos d'une relation entre X et Y, avec un id et un array d'entier pour stocker les id des deux account qui sont copaing.
- On créé un index sur le tableau d'entier.
Exemple:
-- account(id=A, friends_id =(A.friends_id + B))
-- account(id=B, friends_id =(B.friends_id + A))
-- relationships_informations(id, uids=int[A.id, B.id], foo=bar, baz=spam)
On a Deux comptes: A et B
A devient ami avec B.
Donc on ajoute B dans la liste d'amis de A: "account(id=A, friends_id=(A.friends_id + B))"
Puis on ajoute A dans la liste d'amis de B: "account(id=B, friends_id=(B.friends_id + A))"
Enfin on crée une "relationships_info": "relationships_informations(id, uids=int[A.id, B.id], foo=bar, baz=spam)" Avec un array d'entier contenant l'id des deux accounts + toutes les données sur la relation.
Conclusion:
Du coup j'ai plus de tables relation + relation inversé.
Pour récupérer les listes d'amis:
- Je peux facilement récupérer la liste de mes amis.
- Ou la liste des amis de mes amis en concaténant ces listes puis en faisant un uniq(sort(liste_damis_de_mes_amis)), idem pour amis des amis de mes amis et ainsi de suite.
Pour récupérer les infos sur les relations:
- Pour une relation il me suffit de faire un select et de vérifier que la colonne "uids" contient bien mes deux ids.
- Pour plusieurs relations avec l'id d'une personne je peux faire un select dans la table "relationships_infos" sur la colonne "uids" en vérifiant qu'elle contient bien mon id.
- Idem avec l'id de plusieurs personnes en utilisant un "ANY" ou un truc du genre(je ne sais pas si ca existe en SQL).
Après je ne sais pas si je peux créer un type d'array qui doit contenir obligatoirement deux entier différents.
Ce qui éviterait que des données foireuse soient rentrées genre un array de 0,1,3 ou plus d'items.
J'ai vu qu'on pouvait faire un "CREATE UNIQUE INDEX" mais j'imagine que sur une colonne de type array ca doit pas être possible.
Après j'imagine qu'il vaut mieux faire un sort() de chaque array avant enregistrement, pour éviter les doublons du type [1,2], [2,1].
Peut-être qu'un autre type serait envisageable sur la table relationships_infos, je sais pas.
[ Dernière édition du message le 21/02/2020 à 16:32:13 ]

miles1981
8363

Je poste, donc je suis
Membre depuis 20 ans
1890 Posté le 21/02/2020 à 16:47:36
Citation de deozza :
Qu'est-ce que ca apporte en vrai, le nosql par rapport a un sgbdr ? J'ai encore du mal a m'en rendre compte
Pour mon app je suis passe de mysql a mongodb. Parce que je traite que des donnees en json et que mongodb enregistre littéralement en json et que j'ai besoin de rajouter a la volée de nouvelles propriétés sans me prendre la tête avec des migrations. Mais aussi parce que c'est hype, mongodb.
Principalement, tu n'as pas le concept de requetes join. Donc ca change fondamentalement la maniere de voir les schemas de bdd, puisqu'il n'y a plus de schema.
Pour des donnees peu structurees, avec des trous, des listes variables, c'est le top, je trouve.
Apres, c'est aussi que les schemas de bdd, ca me sort par les trous de nez.
Citation de Truelle :
Citation de miles1981 :Perso, pou rce genre de choses, je passe en NoSql et je stocke une liste de chaque cote avec les connexions. Tant que tu n'as pas des milliers de liens, ca peut passer.
Oui mais tu dois bien stocker les informations sur ces connexions quelque part?
Oui, dans la structure associee a la personne. Donc typiquement:
{
id:"",
name:"toto",
connections:["tata", "tutu"]
}
Apres, les problemes de synchro quand on met a jour sont pas simple non plus, mais on peut faire un batch, et si je me souviens bien les batchs font effet de transaction. Donc si tu peux faire un batch, ca va.
Audio Toolkit: http://www.audio-tk.com/
[ Dernière édition du message le 21/02/2020 à 16:48:18 ]
- < Liste des sujets
- Charte