Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1309 connectés 

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  Le NoSQL: MongoDB, Redis, Cassandra, HBase, etc

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Précédente
Auteur Sujet :

Le NoSQL: MongoDB, Redis, Cassandra, HBase, etc

n°2093610
el muchach​o
Comfortably Numb
Posté le 06-08-2011 à 00:12:52  profilanswer
 

J'ouvre un topic sur un sujet très à la mode ces temps-ci, les bases de données non relationnelles.
C'est le mouvement du NoSQL ("Not only SQL" ).

 

L'idée est que les BdD non relationnelles sont plus simples que les SGBD, et permettent en principe d'atteindre des performances plus élevées. D'autres bénéfices importants:
 - les tables sont simplement représentées comme des couples clés-valeurs, avec éventuellement un ou plusieurs index sur les valeurs
 - comme il n'y a pas de schéma, elles peuvent être scalables horizontalement
 - la réplication permet de rendre l'infrastructure plus résistante.

 

Par ailleurs, certaines n'ont pas les garanties ACID apportées par les SGBD. Evidemment, étant donné leurs limitations, elles ne remplacent pas un SGBD, mais sont plutôt complémentaires, pour des usages spécifiques.
Il n'est pas un secret que nombre de grandes sociétées orientées web (Google en premier) font massivement appel au NoSQL. Mais elles sont de plus en plus utilisées ailleurs pour servir de cache de données en backup de la base principale, qui est généralement un SGBD traditionnel.

 

Venez ici discuter de vos retours d'expérience sur ces outils.

 

NB: [:icon4] ce topic n'est pas un topic "pour ou contre le SQL"

 

Une liste de produits: http://nosql-database.org/


Message édité par el muchacho le 17-05-2012 à 06:07:11

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
mood
Publicité
Posté le 06-08-2011 à 00:12:52  profilanswer
 

n°2093611
el muchach​o
Comfortably Numb
Posté le 06-08-2011 à 00:17:47  profilanswer
 

J'ouvre le bal avec Kyoto Cabinet, successeur de Tokyo Cabinet.
 
C'est une simple librairie clefs-valeurs aux performances élevées, qui peut être entièrement en RAM, s'appuyer sur un fichier, ou même sur un système de fichiers. Si celui-ci est distribué, la base peut en profiter. De nombreuses structures de données sont proposées, chacune optimisée pour un type d'application. Il suffit de changer le suffixe du nom de la base pour changer de structure. db.kct est un TreeDB fichier par ex, db.kch est un HashDB.
 
Pour les bases en RAM (à la memcache):
    * time efficiency: CacheDB > StashDB > ProtoHashDB > ProtoTreeDB > GrassDB
    * space efficiency: GrassDB > StashDB > CacheDB > ProtoHashDB > ProtoTreeDB
 
Pour les bases fichier:
    * time efficiency: HashDB > TreeDB > DirDB > ForestDB
    * space efficiency: TreeDB > HashDB > ForestDB > DirDB
 
Il y a un binding pour tous les langages majeurs. Le binding Python est simple bien qu'un peu limité, mais il permet de se servir de KC avec la syntaxe des dictionnaires Python. L'usage en est on ne peut plus simple, ce qui est très attractif.
On peut donc l'utiliser comme une sorte de dictionnaire adossé à un disque de façon transparente, c'est simple et très utile.
Un inconvénient majeur, c'est que la clef et la valeur sont des chaînes de caractères ou des valeurs binaires (au moins en Python). Il faut donc parfois marshaller et unmarshaller les objets, ce qui réduit les performances. L'autre inconvénient est que la base est formée d'un seul fichier qui grossit, et non de plusieurs fichiers. Je pense que ça n'est pas optimal avec pas mal de filesystems.  
J'en parle un peu plus ici.
Les usages évidents de cette librairie sont les caches, le logging, l'indexation, le backup de données.
 
Sur un Core2Duo, le TreeDB en Python les perfs sont excellentes jusqu'à 20 millions d'éléments. Pour le test ci-dessous, le fichier fait alors près de 2Go et la durée des inserts semble croitre exponentiellement avec le nombre d'éléments déjà en base, mais sur moins de 10 millions, la durée est dominée par le marshaling. La durée des retraits est constante.
 
Globalement, c'est un produit comme je les aime: une librairie simple, tout le contraire de l'usine à gaz, qui fait donc relativement peu de choses mais qui les fait bien, et peut donc se révéler très utile en étant immédiatement productive.
 
Un petit prog de test qui ne teste que l'insert et le retrait aléatoire.
Il faut savoir que pour le TreeDB, la clef est triée et que l'on peut itérer sur les éléments en base avec un curseur, ce qui est bcp plus rapide.
 

Code :
  1. # Usage: python kctest.py [num of entries] [db name#options]
  2. # Example: python kctest.py 100000 testdb.kct#tune_buckets=10000
  3. #
  4. from kyotocabinet import *
  5. import sys
  6. import os
  7. import re
  8. import time
  9. import random
  10. import marshal
  11.  
  12. def memoryusage():
  13.    for line in open("/proc/self/status" ):
  14.        line = line.rstrip()
  15.        if line.startswith("VmRSS:" ):
  16.            line = re.sub(r".*:\s*(\d+).*", r"\1", line)
  17.            return float(line) / 1024
  18.    return -1
  19.  
  20. musage = memoryusage()
  21. rnum, bulk_size = 1000000, 10000
  22.  
  23. if len(sys.argv) > 1:
  24.    rnum = int(sys.argv[1])
  25.  
  26. if len(sys.argv) > 2:
  27.    hash = DB()
  28.    if not hash.open(sys.argv[2], DB.OWRITER | DB.OCREATE | DB.OTRUNCATE):
  29.        raise RuntimeError(hash.error())
  30. else:
  31.    print "Using Python dict()"
  32.    hash = {}
  33.  
  34. def bulk_insert(rnum, bulk_size):
  35.    print "========== Bulk inserts =========="
  36.    print "Insert %d items" % rnum
  37.    ttime = 0.0
  38.    stime = etime = time.time()
  39.    sum_itimes = 0
  40.    for step in xrange(0, rnum, bulk_size):
  41.  
  42.        steptime = time.time()
  43.        bulk = {}
  44.        for i in xrange(step, step+bulk_size):
  45.            key = "%08d" % i
  46.            #value = (key, 3.1416, i)
  47.            alea = random.randint(1, rnum*10)
  48.            dec = random.random()
  49.            value = {'index': i,
  50.                      'entier': alea,
  51.                      'chaine': "%20.18f %s" % (dec, alea),
  52.                      'float': dec,
  53.                      'datetime': dec * 1000000000
  54.                     }
  55.            bulk[key] = value
  56.        
  57.        stime = time.time()
  58.        hash.set_bulk(bulk)
  59.        ctime = time.time()
  60.        itime = ctime - stime
  61.        print "Time: %.5f ms bulk insert time:  %.5f ms, %.0f/sec" % ((ctime - steptime)*1000, itime*1000, bulk_size/itime), step
  62.        sum_itimes += itime
  63.    print 'Count:', len(hash)
  64.    print "Total time: %.3f sec, total insertion time: %.3f sec" % ((ctime - etime), sum_itimes)
  65.    
  66. def inserts(rnum):
  67.    print "========== Single inserts =========="
  68.    print "Insert %d items" % rnum
  69.    ttime = 0.0
  70.    stime = time.time()
  71.    for i in xrange(0, rnum):  
  72.        key = "%08d" % i
  73.        #value = (key, 3.1416, i)
  74.        alea = random.randint(1, rnum*10)
  75.        dec = random.random()
  76.        value = {'index': i,
  77.                  'entier': alea,
  78.                  'chaine': "%20.18f %s" % (dec, alea),
  79.                  'float': dec,
  80.                  'datetime': dec * 1000000000
  81.                 }
  82.        hash[key] = marshal.dumps(value)
  83.        if i % 100000 == 0:
  84.            ctime = time.time()
  85.            ttime += ctime - stime
  86.            print "Time: %.3f sec." % (ctime - stime), i
  87.            stime = ctime
  88.    print 'Count:', len(hash)
  89.    print "Time: %.3f sec." %  ttime
  90.  
  91. def retrievals(rnum):
  92.    print "========== Single retrievals =========="
  93.    print "Retrieve %d items" % rnum
  94.    stime = time.time()
  95.    ttime = 0.0
  96.    for i in xrange(0, rnum):
  97.        key = "%08d" % i
  98.        value = marshal.loads(hash.get(key))
  99.        #if value != (key, 3.1416, i):
  100.         #raise ValueError("Retrieved and inserted values do not match !" )
  101.        if i % 100000 == 0:
  102.            ctime = time.time()
  103.            ttime += ctime - stime
  104.         print "Time: %.3f sec." % (ctime - stime), i
  105.            stime = ctime
  106.    print "Time: %.3f sec." % ttime
  107.  
  108.    print "Count: %s" % len(hash)
  109.    print "Usage: %.3f MB" % (memoryusage() - musage)
  110.  
  111.  
  112. if __name__ == '__main__':
  113.  
  114.    bulk_insert(rnum, bulk_size)
  115.    inserts(rnum)
  116.    retrievals(rnum)


Message édité par el muchacho le 07-08-2011 à 09:35:07

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2093612
ratibus
Posté le 06-08-2011 à 00:31:07  profilanswer
 

Ou bien t'es pas obligé de choisir et en utilisant MySQL t'as les 2 :)
http://yoshinorimatsunobu.blogspot [...] y-for.html


---------------
Mon blog
n°2093613
mareek
Et de 3 \o/
Posté le 06-08-2011 à 00:36:28  profilanswer
 

ratibus a écrit :

Ou bien t'es pas obligé de choisir et en utilisant MySQL t'as les 2 :)
http://yoshinorimatsunobu.blogspot [...] y-for.html


Les performances d'un SGBDR avec l'intégrité du NoSQL ?


---------------
"I wonder if the internal negative pressure in self pumping toothpaste tubes is adjusted for different market altitudes." John Carmack
n°2093614
el muchach​o
Comfortably Numb
Posté le 06-08-2011 à 00:56:26  profilanswer
 

Sinon, j'évalue MongoDB, version 1.8.2.
 
MongoDB a ceci de particulier qu'il intègre un langage de requêtes. C'est pas du SQL, mais ça émule ce dernier. On peut donc faire des critères de recherche sur n'importe quelle clef ou valeur en base. Les données sont stockées sous forme de BSON, du JSON binaire.
MongoDB intègre des outils pour du sharding et de la réplication, mais par défaut, n'est pas ACID. Il faut spécifiquement activer la journalisation.
 
Mon problème est que les binaires proposés sur le site n'ont pas l'air optimisés. J'ai eu des performances complètement erratiques sous Windows, et sur mon PC perso sous Linux, j'ai des performances très médiocres comparées à celles obtenues sur un serveur Linux  de mon bureau: 6900 inserts/seconde sur mon C2D (32 bits) contre 20 000/sec sur celui du bureau (64 bits). Mais c'est encore bien pire pour les requêtes, j'ai une différence qui tourne entre un facteur 30 et un facteur 50. P-ê que le disque est bcp plus lent, mais je doute un peu que cela suffise à expliquer de telles différences.Il semblerait que les perfs de cette base soient boostées sur un PC récent. En query, sur une machine récente, on atteint des perfs excellentes de l'ordre de 100 000 à plusieurs centaines de milliers d'objets Python/sec sélectionnés avec plusieurs critères (voir prog ci-dessous), ordonnés selon un champs et récupérés.
 
Mais même avec des différences de disque dur, je ne comprends pas comment on peut obtenir des résultats aussi disparates avec la même version, sur des machines différentes, et curieusement, je ne vois rien sur le site qui explique comment "tuner" la base pour en tirer le maximum. Par ailleurs, si l'espace disque est trop limité, le serveur a tendance à non pas s'arrêter de façon propre, mais à crasher violamment (c'est pourtant la version de production compilée en statique du site).
Enfin, quelle que soit la machine cible, dans mes benchmarks, 98 à 100% du temps CPU est utilisé par Python, ce qui semble indiquer que binding Python, entièrement écrit en Python n'est pas très optimisé et est le bottleneck. Je n'ai pas fait de mesures avec Java et C++.
 
Un prog de test inserts et requêtes:
(Si qq a le loisir de passer mon script de test chez lui, ça m'intéresserait de connaitre les résultats obtenus.)

Code :
  1. # Usage: python mongotest.py num_of_entries bulk_size
  2. # Example: python mongotest.py 100000 1000
  3. #
  4.  
  5. import sys
  6. import os
  7. import re
  8. import time
  9. import datetime
  10. import decimal
  11. import random
  12. import json
  13.  
  14.  
  15.  
  16. def memoryusage():
  17.   for line in open("/proc/self/status" ):
  18.       line = line.rstrip()
  19.       if line.startswith("VmRSS:" ):
  20.           line = re.sub(r".*:\s*(\d+).*", r"\1", line)
  21.           return float(line) / 1024
  22.   return -1
  23.  
  24.  
  25.  
  26. rnum = 1000000
  27. fname = 'documents.txt'
  28. if len(sys.argv) > 1:
  29.   rnum = int(sys.argv[1])
  30.   bulk_size = int(sys.argv[2])
  31.  
  32.  
  33. def bulk_insert(rnum, bulk_size):
  34.    random.seed(17)
  35.  
  36.    print "Insert %d items" % rnum
  37.  
  38.    f = open(fname, 'r')
  39.    if 'posts' in db.collection_names():
  40.        print 'cleaning db.posts'
  41.        db.drop_collection('posts')
  42.        print db.posts.count()
  43.  
  44.    posts = db.posts
  45.    ttime = time.time()
  46.    sum_itimes = 0
  47.    
  48.    for step in xrange(0, rnum, bulk_size):
  49.        steptime = time.time()
  50.        bulk = []
  51.        for i in xrange(step, step+bulk_size):
  52.            r = json.loads(f.readline())
  53.            r['datetime'] = datetime.datetime.fromtimestamp(r['datetime'])
  54.            bulk.append(r)      
  55.  
  56.        stime = time.time()
  57.        posts.insert(bulk)
  58.        ctime = time.time()
  59.        itime = ctime - stime
  60.        print "Time: %.3f sec insertion time:  %.3f sec, %.3f/sec" % (ctime - steptime, itime, bulk_size/itime), step
  61.        sum_itimes += itime
  62.    etime = time.time()
  63.  
  64.    print 'Number of docs in posts', posts.count()
  65.    print "Total time: %.3f sec, total insertion time: %.3f sec" % ((etime - ttime), sum_itimes)
  66.  
  67. def retrievals():
  68.    random.seed(17)
  69.    print "==========Indexing==========="
  70.  
  71.    db.posts.create_index('entier')
  72.    stime = time.time()
  73.    sum_itimes = 0
  74.  
  75.    print "==========Sorted Queries==========="
  76.    sum_num = 0
  77.    ttime = time.time()
  78.    for i in xrange(0, 10):      
  79.        dec = random.random()
  80.      
  81.        a_date = datetime.datetime.fromtimestamp(dec * 1000000000)
  82.        query = { 'datetime': {'$gt': a_date}, 'float': {'$gt': dec, '$lt': dec+0.25} }
  83.        num = 0
  84.        stime = time.time()
  85.        db.posts.find(query).count()
  86.        for num, record in enumerate(db.posts.find(query)):
  87.            pass
  88.  
  89.        ctime = time.time()
  90.        itime = ctime - stime
  91.        sum_num += num
  92.        sum_itimes += itime
  93.        form = "Time: %.3f sec. to fetch %s records (datetime > %s, float > x=%f < x+0.25)"
  94.        print form % (itime, num, a_date, dec)
  95.  
  96.    etime = time.time()
  97.    print "%s records retrieved retrieved in %.3f sec." % (sum_num, sum_itimes)
  98.    print "Total time: %.3f sec., total query time: %.2f sec." % ((etime - ttime), sum_itimes)    
  99.  
  100. def generate(rnum):
  101.    f = open(fname, 'w')
  102.    print 'Generating random %s documents' % rnum
  103.  
  104.    random.seed(17)
  105.  
  106.    for i in xrange(0, rnum):
  107.        # a random record
  108.        alea = random.randint(1, rnum*10)
  109.        dec = random.random()
  110.  
  111.        record = {'index': i,
  112.                  'entier': alea,
  113.                  'chaine': "%20.18f %s" % (dec, alea),
  114.                  'float': dec,
  115.                  'datetime': dec * 1000000000
  116.                 }
  117.  
  118.        dump = json.dumps(record, separators=(',',':'))
  119.        f.write(dump + '\n')
  120.  
  121. if __name__ == '__main__':
  122.  
  123.    from pymongo import Connection  
  124.  
  125.    if not os.path.exists(fname):
  126.        generate(rnum)
  127.    
  128.    connection = Connection('localhost', 27017)
  129.    db = connection.test_database
  130.    
  131.    bulk_insert(rnum, bulk_size)
  132.    retrievals()
  133.  
  134.    print "Used memory %d Mb" % memoryusage()


 
Exemple de sortie sur ma machine:


(myenv)nicolas@gromit:~/myenv$ python mongo_test.py 100000 500
Generating random 100000 documents
Insert 100000 items
cleaning db.posts
0
Time: 0.153 sec insertion time:  0.073 sec, 6868.229/sec 0
Time: 0.165 sec insertion time:  0.072 sec, 6922.322/sec 500
Time: 0.161 sec insertion time:  0.072 sec, 6950.910/sec 1000
Time: 0.167 sec insertion time:  0.072 sec, 6947.640/sec 1500
..........
Time: 0.166 sec insertion time:  0.072 sec, 6899.116/sec 99500
Number of docs in posts 100000
Total time: 32.603 sec, total insertion time: 14.283 sec
==========Indexing===========
==========Sorted Queries===========
Time: 288.215 sec. to fetch 96032 records (datetime < 2000-06-08 22:06:14.323877, float > x=0.960495 < x+0.25)
Time: 8.254 sec. to fetch 11024 records (datetime < 1973-06-29 01:34:08.917212, float > x=0.110162 < x+0.25)
Time: 221.906 sec. to fetch 74616 records (datetime < 1993-08-26 21:59:56.166384, float > x=0.746395 < x+0.25)
Time: 285.353 sec. to fetch 94498 records (datetime < 1999-12-14 18:51:54.504889, float > x=0.945194 < x+0.25)
Time: 263.617 sec. to fetch 87489 records (datetime < 1997-09-27 01:28:22.128281, float > x=0.875317 < x+0.25)
Time: 40.043 sec. to fetch 20844 records (datetime < 1976-08-27 18:06:49.490222, float > x=0.210010 < x+0.25)
Time: 195.412 sec. to fetch 63855 records (datetime < 1990-03-30 06:59:41.059796, float > x=0.638773 < x+0.25)
Time: 130.868 sec. to fetch 47521 records (datetime < 1985-01-09 07:01:11.106405, float > x=0.474098 < x+0.25)
Time: 239.179 sec. to fetch 81286 records (datetime < 1995-10-11 03:22:01.749089, float > x=0.813378 < x+0.25)
Time: 239.588 sec. to fetch 75193 records (datetime < 1993-10-31 03:33:53.571964, float > x=0.752035 < x+0.25)
652358 records retrieved retrieved in 1912.435 sec.
Total time: 1912.436 sec., total query time: 1912.44 sec.
Used memory 46 Mb


Ces mêmes queries tournent autour de la fraction de seconde a la seconde sur un autre PC. Je ne comprends pas bien ces résultats.


Message édité par el muchacho le 06-08-2011 à 21:23:29

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2093623
ratibus
Posté le 06-08-2011 à 09:11:00  profilanswer
 

mareek a écrit :


Les performances d'un SGBDR avec l'intégrité du NoSQL ?


Ca commence à troller sur MySQL :/


---------------
Mon blog
n°2093626
el muchach​o
Comfortably Numb
Posté le 06-08-2011 à 09:46:35  profilanswer
 

ratibus a écrit :

Ou bien t'es pas obligé de choisir et en utilisant MySQL t'as les 2 :)
http://yoshinorimatsunobu.blogspot [...] y-for.html


Intéressant.
Ici un post comparant un MySQL "normal" et MongoDB. Pas sûr qu'il ait bien indexé MySQL pour obtenir de telles différences, ou alors sa base était entièrement en RAM ?


Message édité par el muchacho le 06-08-2011 à 10:08:24

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2093629
verdoux
And I'm still waiting
Posté le 06-08-2011 à 10:19:53  profilanswer
 

Ce comparatif est ridicule.

n°2093630
el muchach​o
Comfortably Numb
Posté le 06-08-2011 à 10:24:48  profilanswer
 

Je pense aussi. Vu qu'on n'a plus accès aux sources, on ne sait pas s'il a indexé la base, ni si ce sont des queries avec un résultat unitaires ou retournant un certains nombre d'éléments, etc.


Message édité par el muchacho le 06-08-2011 à 10:27:41

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2093635
ratibus
Posté le 06-08-2011 à 11:32:03  profilanswer
 

verdoux a écrit :

Ce comparatif est ridicule.


+1
 
Pour le DELETE : il pourrait faire un TRUNCATE vu qu'il a pas de critère dans son DELETE
Pour le SELECT : c'est indexé vu que la colonne k est PK (mais pour faire du PK lookup faut utiliser ce que j'ai mis + haut). Il utilise même pas de prepared statement.
Pour les INSERT : il utilise pas d'INSERT bulk ou de LOAD DATA donc oui les perfs ça fait mal.
 
Bref, il sait pas utiliser MySQL :o


---------------
Mon blog
mood
Publicité
Posté le 06-08-2011 à 11:32:03  profilanswer
 

n°2093649
verdoux
And I'm still waiting
Posté le 06-08-2011 à 13:45:58  profilanswer
 

J'obtiens ça sur un netbook (atom n550 1,5GHz):

Citation :


 
Number of docs in posts 100000
Total time: 19.710 sec, total insertion time: 7.371 sec
==========Indexing===========
==========Sorted Queries===========
Time: 3.432 sec. to fetch 52315 records (datetime < 1986-07-17 13:31:49.712493, float > x=0.521984 < x+0.25)
Time: 4.902 sec. to fetch 80629 records (datetime < 1995-07-25 18:46:17.118679, float > x=0.806691 < x+0.25)
Time: 5.761 sec. to fetch 96032 records (datetime < 2000-06-08 22:06:14.323877, float > x=0.960495 < x+0.25)
Time: 2.113 sec. to fetch 28968 records (datetime < 1979-03-07 04:29:37.764466, float > x=0.289625 < x+0.25)
Time: 4.691 sec. to fetch 76597 records (datetime < 1994-04-12 01:37:17.797953, float > x=0.766107 < x+0.25)
Time: 4.355 sec. to fetch 70374 records (datetime < 1992-04-25 18:37:46.843413, float > x=0.704220 < x+0.25)
Time: 4.143 sec. to fetch 66121 records (datetime < 1990-12-16 22:30:57.223830, float > x=0.661383 < x+0.25)
Time: 1.127 sec. to fetch 11024 records (datetime < 1973-06-29 01:34:08.917212, float > x=0.110162 < x+0.25)
Time: 0.691 sec. to fetch 2699 records (datetime < 1970-11-08 19:26:18.790527, float > x=0.026937 < x+0.25)
Time: 2.605 sec. to fetch 38520 records (datetime < 1982-03-05 11:11:44.544297, float > x=0.384171 < x+0.25)
523279 records retrieved retrieved in 33.819 sec.
Total time: 33.821 sec., total query time: 33.82 sec.
Used memory 17 Mb

n°2093658
el muchach​o
Comfortably Numb
Posté le 06-08-2011 à 14:31:03  profilanswer
 

OK, ça parait cohérent avec les résultats des autres machines. Je ne comprends pas pourquoi ça rame autant sur mon C2D@2GHz. :/


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2093659
verdoux
And I'm still waiting
Posté le 06-08-2011 à 14:32:24  profilanswer
 

T'as pensé à mettre à jour ta zlib ?
 
 :whistle:

n°2093660
el muchach​o
Comfortably Numb
Posté le 06-08-2011 à 14:34:56  profilanswer
 

:D [:natas]

 

Nan mais y'a un vrai pb sur ma machine, on dirait, même en insertion, c'est plus lent que ton netbook. Ceci dit, sous XP, au boulot, j'ai eu aussi des perfs anormalement mauvaises, du genre 1 record/seconde (pas d'antivirus). Mais si ça se trouve, les données passaient par le réseau...

 

edit:

 

Bon, mongostat m'indique que la base ne fait rien la plupart du temps, et les commandes:

db.setProfilingLevel(2);
db.system.profile.find( { millis : { $gt : 50 } } )

 

m'indiquent qu'aucune requête n'a pris plus de 150 ms. On dirait qu'iIl y a de mon coté un pb de communication entre la base et le driver Python. D'ailleurs, mongod occupe 0% du CPU tandis que Python mouline comme un coureur du tour de France...

 

edit: j'avais oublié que j'avais le driver pur Python et non le driver écrit en C...


Message édité par el muchacho le 06-08-2011 à 20:48:26

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2093678
el muchach​o
Comfortably Numb
Posté le 06-08-2011 à 17:25:06  profilanswer
 

Pour comparer, même programme mais avec SQLite 3 (qui est inclus par défaut dans la distrib Python). Vous avez quoi comme perfs ?

 
Code :
  1. import sys
  2. import os
  3. import re
  4. import time
  5. import datetime
  6. import decimal
  7. import random
  8. import json
  9. import sqlite3
  10.  
  11. def memoryusage():
  12.   for line in open("/proc/self/status" ):
  13.       line = line.rstrip()
  14.       if line.startswith("VmRSS:" ):
  15.           line = re.sub(r".*:\s*(\d+).*", r"\1", line)
  16.           return float(line) / 1024
  17.   return -1
  18.  
  19. rnum = 1000000
  20. fname = 'documents.txt'
  21. if len(sys.argv) > 1:
  22.   rnum = int(sys.argv[1])
  23.   bulk_size = int(sys.argv[2])
  24.  
  25. def bulk_insert(conn, rnum, bulk_size):
  26.    random.seed(17)
  27.    
  28.    c = conn.cursor()
  29.    c.execute("drop table if exists record" )
  30.    c.execute('''create table if not exists record (idx integer,
  31.                                      chaine text,
  32.                                      float real,
  33.                                      entier integer,
  34.                                      datetime real)''')
  35.  
  36.    print "Insert %d items" % rnum
  37.    
  38.    f = open(fname, 'r')
  39.    ttime = time.time()
  40.    sum_itimes = 0
  41.    
  42.    for step in xrange(0, rnum, bulk_size):
  43.  
  44.        def tuple_gen():
  45.            for i in xrange(step, step+bulk_size):
  46.                r = json.loads(f.readline())
  47.                #r['datetime'] = datetime.datetime.fromtimestamp(r['datetime'])
  48.                yield tuple(r.values())
  49.  
  50.        steptime = time.time()        
  51.        stime = time.time()
  52.        c.executemany("insert into record values (?,?,?,?,?)", tuple_gen())
  53.        conn.commit()
  54.        ctime = time.time()
  55.        itime = ctime - stime
  56.        print "Time: %.3f sec insertion time:  %.3f sec, %.3f/sec" % (ctime - steptime, itime, bulk_size/itime), step
  57.        sum_itimes += itime
  58.    etime = time.time()
  59.    print 'Number of docs in record table:', c.execute("select count(*) from record" ).fetchone()[0]
  60.    print "Total time: %.3f sec, total insertion time: %.3f sec" % ((etime - ttime), sum_itimes)
  61.    
  62. def retrievals(conn):
  63.    random.seed(17)
  64.    c = conn.cursor()
  65.  
  66.    print "==========Indexing================"
  67.    c.execute("create index if not exists entier_idx on record(entier)" )
  68.    c.execute("analyze" )
  69.    #c.execute("create index if not exists datetime_idx on record(datetime)" )
  70.    #c.execute("create index if not exists float_idx on record(float)" )
  71.    stime = time.time()
  72.    sum_itimes = 0
  73.  
  74.    print "==========Sorted Queries==========="
  75.    sum_num = 0
  76.    ttime = time.time()
  77.    for i in xrange(0, 10):      
  78.        dec = random.random()
  79.        
  80.        a_date = datetime.datetime.fromtimestamp(dec * 1E9)
  81.        num = 0
  82.        stime = time.time()
  83.        query = "select * from record where datetime > %s and (float > %s and float < %s)" % (dec*1E9, dec, dec+0.25)
  84.        c.execute(query)
  85.        for num, record in enumerate(c):
  86.            pass
  87.        ctime = time.time()
  88.        itime = ctime - stime
  89.        sum_num += num
  90.        sum_itimes += itime
  91.        form = "Time: %.3f sec. to fetch %s records (datetime > %s, float > x=%f < x+0.25)"
  92.        print form % (itime, num, a_date, dec)
  93.    etime = time.time()
  94.    print "%s records retrieved retrieved in %.3f sec." % (sum_num, sum_itimes)
  95.    print "Total time: %.3f sec., total query time: %.2f sec." % ((etime - ttime), sum_itimes)
  96.  
  97. def generate(rnum):
  98.    f = open(fname, 'w')
  99.    print 'Generating random %s documents' % rnum
  100.    random.seed(17)
  101.    for i in xrange(0, rnum):
  102.        # a random record
  103.        alea = random.randint(1, rnum*10)
  104.        dec = random.random()
  105.        record = {'index': i,
  106.                  'entier': alea,
  107.                  'chaine': "%20.18f %s" % (dec, alea),
  108.                  'float': dec,
  109.                  'datetime': dec * 1000000000
  110.                 }
  111.        dump = json.dumps(record, separators=(',',':'))
  112.        f.write(dump + '\n')
  113.    
  114. if __name__ == '__main__':
  115.    
  116.    if not os.path.exists(fname):
  117.        generate(rnum)
  118.    
  119.    conn = sqlite3.connect('sqlite.db')
  120.    
  121.    bulk_insert(conn, rnum, bulk_size)
  122.    retrievals(conn)
  123.    print "Used memory %d Mb" % memoryusage()



> python sqlite_test.py 1000000 5000

 

...
Number of docs in record table: 1000000
Total time: 164.432 sec, total insertion time: 164.421 sec
==========Sorted Queries===========
Time: 1.990 sec. to fetch 249503 records (datetime > 1986-07-17 13:31:49.712493, float > x=0.521984 < x+0.25)
Time: 1.626 sec. to fetch 193353 records (datetime > 1995-07-25 18:46:17.118679, float > x=0.806691 < x+0.25)
Time: 0.849 sec. to fetch 39576 records (datetime > 2000-06-08 22:06:14.323877, float > x=0.960495 < x+0.25)
Time: 2.105 sec. to fetch 250627 records (datetime > 1979-03-07 04:29:37.764466, float > x=0.289625 < x+0.25)
Time: 1.817 sec. to fetch 233786 records (datetime > 1994-04-12 01:37:17.797953, float > x=0.766107 < x+0.25)
Time: 1.921 sec. to fetch 249910 records (datetime > 1992-04-25 18:37:46.843413, float > x=0.704220 < x+0.25)
Time: 1.946 sec. to fetch 250174 records (datetime > 1990-12-16 22:30:57.223830, float > x=0.661383 < x+0.25)
Time: 2.156 sec. to fetch 249436 records (datetime > 1973-06-29 01:34:08.917212, float > x=0.110162 < x+0.25)
Time: 2.182 sec. to fetch 249905 records (datetime > 1970-11-08 19:26:18.790527, float > x=0.026937 < x+0.25)
Time: 2.080 sec. to fetch 250116 records (datetime > 1982-03-05 11:11:44.544297, float > x=0.384171 < x+0.25)
2216386 records retrieved retrieved in 18.671 sec.
Total time: 18.672 sec., total query time: 18.67 sec.
Used memory 7 Mb

 


Les perfs sont excellentes. A noter que sans la clause ORDER BY, les requêtes s'exécutent en 9,6 sec au lieu de 37,5 sec.
Curieusement, le fait d'ajouter un index sur cette colonne à la création de la table fait que l'insertion ralentit considérablement. On passe de 6000 à moins de 1000 insertions/sec.
verdoux, tu as quoi, comme résultats ?
En outre, il faut savoir que SQLite ne vérifie pas les types de données (typage dynamique), contrairement aux SGBDR traditionnels. Les données peuvent être corrompues.


Message édité par el muchacho le 07-08-2011 à 12:24:04

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2093711
el muchach​o
Comfortably Numb
Posté le 06-08-2011 à 20:46:46  profilanswer
 

OK, problem solved.
Via easy_install, j'avais installé le driver pur Python et non le driver C. Maintenant, les insertions via Pymongo se font à 48 000/sec (sauf qu'elles ne sont pas forcément écrites sur disque instantanément). Les requêtes ne sont pas extrêmement rapides, mais prennent autour de 7 secondes pour 250 000 lignes sur une base d'un million. C'est pas mal, mais c'est plus lent que SQLite. Dans ces tests, MongoDB est 8 fois plus rapide en insertion, et 4 fois plus lent en query, via leurs drivers Python respectifs. Reste que la vitesse du disque est primordiale et les tests en query sur un SSD donnent des vitesses très élevées. Globalement, les perfs sur un seul node sont satisfaisantes au regard des possibilités offertes par la base. Je n'ai pas fait de tests en cluster.

 

Comme la base est memory mapped, MongoDB ne fonctionnera pas sur des bases de plusieurs millions de lignes en 32 bits. Il faut obligatoirement un OS 64 bits.


Message édité par el muchacho le 06-11-2011 à 16:54:54

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2093748
el muchach​o
Comfortably Numb
Posté le 07-08-2011 à 00:28:21  profilanswer
 
n°2093770
verdoux
And I'm still waiting
Posté le 07-08-2011 à 10:50:01  profilanswer
 
n°2093946
el muchach​o
Comfortably Numb
Posté le 08-08-2011 à 14:54:39  profilanswer
 

Quelques liens utiles:

 

http://nosql.mypopescu.com/post/61 [...] experience
http://kkovacs.eu/cassandra-vs-mon [...] b-vs-redis
http://code.google.com/p/scalable-frameworks/
http://www.slideshare.net/ksankar/nosql-4559402

 

Le diagramme ci-dessous fait référence au "théorème CAP" qui dit qu'un système distribué ne peut pas satisfaire plus de deux propriétés simultanément parmi les 3 que sont Partition tolerance, Availibility et Consistency.
Les différentes bases garantissent donc seulement deux de ces propriétés. L'application envisagée doit impérativement tenir compte de ces limitations.

 

Sinon, d'un point de vue conceptuel, il me semble que les bases orientées "tables" façon BigTable sont plus complexes à appréhender que les bases orientées documents comme MongoDB, qui se prêtent bien à la programmation OO, chaque document représentant une hiérarchie d'objets; tandis que les bases orientées clefs-valeurs sont les plus simples, et peuvent être utilisées comme des dictionnaires améliorés.

 

http://posterous.com/getfile/files.posterous.com/nahurst/IAHBjwAxcmieJzvtqqyIgriyIzqquwwxumguABujzlzHEbEeJgvhCFcriika/media_httpfarm5static_mevIk.png.scaled1000.png

 

http://pl.atyp.us/images/visual_guide.png


Message édité par el muchacho le 31-01-2014 à 22:00:20

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2094210
el muchach​o
Comfortably Numb
Posté le 09-08-2011 à 15:55:57  profilanswer
 

Cassandra, ou le NoSQL qui rajoute une couche... de SQL... :D

 

Rien de très étonnant. Cassandra/HBase/BigTable sont des bases NoSQL avec schéma.

 

Les concepts de Cassandra/HBase/BigTable sont bcp plus clairs si on fait la correspondance:


Cassandra       SQL
--------------------
Column          colonne
SuperColumn    ligne
ColumnFamily   table


Il n'y a pas de jointure dans Cassandra, parce que que les ColumnFamilys peuvent contenir d'autres ColumnFamilys, ce qui revient effectivement à faire l'équivalent d'une jointure.
Dans Cassandra, les supercolumns et les columns sont des dictionnaires clefs-valeurs. L'absence d'une clef correspond à un NULL dans une table SQL.
Donc les concepts sont équivalents, ce qui explique le fait qu'on puisse faire un SQL par dessus les tables Cassandra.
Il y a cependant une différence majeure, qui est que dans Cassandra, les columns et les Supercolumns sont triées par défaut, contrairement aux RDBMS. L'avantage est un gain certains de perfs. Il est possible d'obtenir des données en sens inverse via SliceRange tant que le nombre de données requêté tient en RAM, ça n'est donc pas aussi performant qu'un ORDER BY d'un RDBMS.


Message édité par el muchacho le 17-02-2013 à 04:21:47

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2110023
el muchach​o
Comfortably Numb
Posté le 06-11-2011 à 14:35:24  profilanswer
 

Bon, MongoDB a mauvaise presse ces temp-ci:
http://news.ycombinator.com/item?id=3202081
http://news.ycombinator.com/item?id=3200683
Réponse du boss de 10gen:http://news.ycombinator.com/item?id=3202959
En particulier, les multiples posts indiquant des pertes de données (même avec une version 2.0),sont particulièrement inquiétants, donnant l'impression que ce produit n'est pas mature.


Message édité par el muchacho le 06-11-2011 à 18:21:54

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2110336
___alt
Posté le 08-11-2011 à 14:43:04  profilanswer
 

Fais ressortir la réponse du boss quand même, ça met en lumière que les posts précédents étaient de la merde : http://news.ycombinator.com/item?id=3202959


---------------
TRIPS RIGHT BUNCH F SHUTTLE TOM AND JERRY RIGHT YELLOW
n°2136532
el muchach​o
Comfortably Numb
Posté le 14-04-2012 à 11:48:50  profilanswer
 

Non, ça n'était pas de la merde.
http://blog.engineering.kiip.me/po [...] th-mongodb
 
MongoDB n'est manifestement pas un outil fiable.


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2136798
___alt
Posté le 16-04-2012 à 10:19:38  profilanswer
 

el muchacho a écrit :

Non, ça n'était pas de la merde.
http://blog.engineering.kiip.me/po [...] th-mongodb
 
MongoDB n'est manifestement pas un outil fiable.


 
Si, c'était un peu de la merde. Y'a quand même un monde entre : "l'intégrité des données n'est pas garantie" et "l'exploitation de MongoDB est délicate du fait de certains problèmes liés aux performances".


---------------
TRIPS RIGHT BUNCH F SHUTTLE TOM AND JERRY RIGHT YELLOW
n°2142780
el muchach​o
Comfortably Numb
Posté le 17-05-2012 à 05:50:19  profilanswer
 

Et encore des gens qui lâchent mongodb:
http://www.korokithakis.net/posts/ [...] 3-i-guess/
http://www.zopyx.de/blog/goodbye-mongodb <-- disparu
http://news.ycombinator.com/item?id=4477974

 

Toujours les mêmes raisons.


Message édité par el muchacho le 17-02-2013 à 11:59:29

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2147053
java8
Posté le 25-06-2012 à 15:23:38  profilanswer
 

Bonjour à tous,
 
Voilà dans le cadre de mon stage je dois effectuer une étude dans laquelle je dois récolter plusieurs tests de performances effectués sur MongoDB (écriture, lecture, update) afin de pouvoir en connaitre les avantages et les limites pour un futur projet. Et ainsi superposer les différents tests trouvés selon la taille de l'objet, le nombre de clients, quel driver de langage utilisé.
 
Jusque là je me sens un peu bloqué sur la démarche à adopter. En effet je suis surtout habitué à faire du développement classique et je ne suis pas très  à l'aise avec ce genre d'exercice "tout seul".  J'aurais vraiment besoin d'aide, même en MP. j'aurais peut être besoin de l'expertise d'un expert MongoDB.
 
Merci d'avance pour votre contribution quelle qu'elle soit.
 

n°2176098
el muchach​o
Comfortably Numb
Posté le 17-02-2013 à 05:32:07  profilanswer
 

Une bonne comparaison entre les deux éléphants des bases de données distribuées open source:
http://bigdatanoob.blogspot.fr/201 [...] andra.html

 

Les deux systèmes sont capables de gérer des clusters de centaines de serveurs, et des centaines de To de données, avec réplication entre data centers. Les performances des deux systèmes ont considérablement avancé, de même que leurs fonctionnalités respectives.
Performances
Ce benchmark montre qu'à part dans le cas d'une base où les lectures sont fortement majoritaires, où un shard de MySQL est vainqueur, HBase et Cassandra dominent largement, ce qui n'a rien de surprenant dans la mesure où ces bases sont optimisées pour l'écriture sous forte concurrence.
Difficile de savoir lequel est le plus rapide des deux. HBase a la réputation d'être très rapide (Facebook, après avoir développé Cassandra, a décidé de partir sur HBase pour son système de messaging), mais semble nettement plus compliqué à administrer.


Message édité par el muchacho le 17-02-2013 à 18:51:19

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2177214
el muchach​o
Comfortably Numb
Posté le 23-02-2013 à 17:10:38  profilanswer
 
n°2191740
el muchach​o
Comfortably Numb
Posté le 26-05-2013 à 09:11:52  profilanswer
 

Excellente conférence de Martin Fowler: http://www.youtube.com/watch?v=qI_g07C_Q5I
Visionnage recommandé.


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2210451
el muchach​o
Comfortably Numb
Posté le 16-11-2013 à 11:26:43  profilanswer
 

Article intéressant: NoSQL data modeling
 
 
et en bonus:
 
http://www.ibmbigdatahub.com/sites/default/files/infographic_file/4-Vs-of-big-data.jpg


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2210456
rufo
Pas me confondre avec Lycos!
Posté le 16-11-2013 à 12:07:25  profilanswer
 

Je dois avouer que jusqu'à présent, je voyais le NoSQL utile uniquement pour du décisionnel...
 
Edit: en tout cas, topic très intéressant (j'ai bien aimé le lien sur Mysql et le HandlerSocket) ;)


Message édité par rufo le 16-11-2013 à 12:08:16

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2210465
el muchach​o
Comfortably Numb
Posté le 16-11-2013 à 14:17:34  profilanswer
 

Non, c'est utilisé pour de la transaction aussi. Par exemple, la distribution de colis à La Poste est maintenant gérée sous Cassandra.


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2210541
Oliiii
Posté le 18-11-2013 à 08:33:20  profilanswer
 

Ça c'est un truc que je ne comprends pas.
La distribution de colis c'est bien trop petit pour justifier du noSQL.
 
Avec 4.000.000 de colis par jours on est même pas a 50/s, même si il y a des pics a 500/s voir même 5000/s ça reste toujours a portée de n'importe quel server avec 2 bête cores et un minimum d'optimisation.
 
Le reste c'est du web server qui peut augmenter en capacité de façon pratiquement linéaire. Et tout ça sans même parler de l'utilisation de cache et d'optimisation un peut plus poussée.

Message cité 1 fois
Message édité par Oliiii le 18-11-2013 à 08:33:47
n°2210555
rufo
Pas me confondre avec Lycos!
Posté le 18-11-2013 à 10:39:39  profilanswer
 

el muchacho a écrit :

Non, c'est utilisé pour de la transaction aussi. Par exemple, la distribution de colis à La Poste est maintenant gérée sous Cassandra.


Faut avouer que la gestion de la distribution de colis, ça nécessite pas beaucoup de tables :/ La clé est le n° du colis, après y'a qq dates et lieux associés pour avoir le parcours.
 
Maintenant, je vois mal du NoSQL pour un outil de help-desk, par ex, ou une base de connaissance style Wikipedia :/


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2218285
el muchach​o
Comfortably Numb
Posté le 31-01-2014 à 21:43:25  profilanswer
 

Oliiii a écrit :

Ça c'est un truc que je ne comprends pas.
La distribution de colis c'est bien trop petit pour justifier du noSQL.

 

Avec 4.000.000 de colis par jours on est même pas a 50/s, même si il y a des pics a 500/s voir même 5000/s ça reste toujours a portée de n'importe quel server avec 2 bête cores et un minimum d'optimisation.

 

Le reste c'est du web server qui peut augmenter en capacité de façon pratiquement linéaire. Et tout ça sans même parler de l'utilisation de cache et d'optimisation un peut plus poussée.


Ca fait 1,46 milliards de colis-lignes/an Ils ne gardent que 15j de données. Il y a effectivement des pics de transactions de plusieurs milliers de lignes/s en fin d'année, ce qui n'est possible en insert que pour une table complètement dénormalisée, et bien sûr un uptime > 99, 99%. Ca me paraît un use case raisonnable pour du NoSQL. Apparemment, ils venaient de MySQL (un shard ?).

Message cité 1 fois
Message édité par el muchacho le 31-01-2014 à 21:52:55

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2218286
flo850
moi je
Posté le 31-01-2014 à 21:48:15  profilanswer
 

c'est utilisé pour un projet de gestio des oevures d'art( gertrude ) pour sa facilité a gérer de la petite cuillère au chateau  
Ils utilisent mongodb  
 
 


---------------

n°2218289
el muchach​o
Comfortably Numb
Posté le 31-01-2014 à 23:11:37  profilanswer
 

Je dois dire que Cassandra a une architecture tout à fait intéressante et séduisante. Elle est basée sur Google BigTable pour le modèle de données et Amazon Dynamo pour l'archi réseau. En fait Cassandra est une implémentation pratiquement complète de l'architecture Dynamo. A noter que Riak est aussi une implémentation de l'architecture dynamo, mais le modèle de données est simplement un modèle clef-valeur.

 

Le modèle de données

 

Le modèle de données est de façon schématique une DistributedHashMap<rowkey, SortedHashMap<column name, value>>, où value peut être un objet ou une collection, et column name peut être une clef composite. Ce modèle est l'équivalent d'un ensemble dénormalisé de tables  dans un SGBD relationnel, et s'appelle une ColumnFamily dans la terminologie Cassandra.
http://javamaster.files.wordpress.com/2010/03/cassandra_data_model.png
La SortedHashMap peut contenir jusqu'à 2 milliards de paires <Column Name, value> et le nombre de rows n'est pas limité. A noter que value peut être absent et c'est une pratique courante de se servir des Column Names pour contenir les valeurs elles-mêmes.

 

Pour donner un exemple de la façon dont on se sert de ce modèle, voici un schéma relationnel.
http://www.datastax.com/docs/_images/relational_model.png
Et le schéma Cassandra équivalent.
http://www.datastax.com/docs/_images/cassandra_model.png
On constate que le modèle relationnel décrit de façon compacte les relations entre les entités. Une vue particulière sur les données sera créée dynamiquement lors des requêtes grâce à des jointures. Parce que le modèle Cassandra est essentiellement dénormalisé, il décrit une seule vue des relations entre les entités, il ne possède pas la souplesse d'un SGBD relationnel. Chaque vue supplémentaire sur les données nécessitera d'ajouter une table d'indexation sous la forme d'une Column Family supplémentaire. Cela pourrait se comparer à une vue matérialisée d'un SGBDR. A noter que le schéma non relationnel de BigTable se prête plus plus facilement à un mapping orienté objet que le modèle relationnel, car un objet peut être sérialisé et relu de façon séquentielle, - et donc efficiente -, dans/depuis une ColumnFamily.

 

Le token ring et la répartition des données

 

Ce modèle de données est conditionné par l'organisation physique du système. Dans l'architecture dynamo, les serveurs/nodes sont tous identiques et organisés en un token ring.

 

http://www.datastax.com/docs/_images/multirack_tokens.png

 


Chaque row d'une ColumnFamily réside sur un même serveur, avec toutes les données associées, celles qui seraient jointes par des relations dans un SGBD relationnel. Ainsi l'on préserve la localité des données, ce qui est vital pour les performances.

 

La rowkey est une clef de hachage (MurMur3) qui permet de répartir les rows uniformément entre les nodes (plus de détails ici).

 

http://paperplanes-assets.s3.amazonaws.com/consistent-hashing.png
On égalise ainsi automatiquement les données et donc la charge, ce qui est plus délicat avec un sharding MySQL naïf (par exemple pour des time series, les données les plus récentes sont souvent les plus souvent accédées). A noter que chaque node physique contient 256 virtual nodes, ce qui permet de répartir encore mieux les données dans de petits clusters. Lorsqu'un node physique est rajouté/enlevé, les données des vnodes sont automatiquement réparties pour équilibrer la charge.

 

La réplication en temps réel

 

Pour assurer la redondance des données, chaque row est répliqué N fois (facteur de réplication) sur des nodes distincts via peer-to-peer. Cassandra est capable de répartir les données sur des baies différentes, et de faire de la réplication en temps réel entre plusieurs data centers ou entre un data center et un cloud. En général, N = 3 dans un même data center et des baies distinctes est e type de réplication le plus courant. Les débits et latences d'écriture tiennent compte de ces réplications.

 

Si N > 1, cependant, le délai induit par la réplication fait que pendant quelques ms à quelques centaines de ms (en fonction de la topologie physique du token ring et des diverses réplications en jeu), les serveurs ne sont pas tous synchronisés. Si une requête tombe sur l'une des copies non synchronisées, elle ne retournera pas le résultat escompté: on dit que Cassandra est une base "éventuellement consistante". Le degré de consistance est configurable par requête: on peut par exemple pour une requête donnée interroger un seul serveur (consistency level = 1), au moins N/2+1 serveurs (consistency level = LOCAL_QUORUM), ou les N serveurs sur un même data center (consistency = ALL). Le tradeoff sera donc entre la consistance et la latence (le C et le Availability du théorème CAP), en fonction des besoins. Une BD qui ne retourne pas systématiquement le bon résultat a-t'elle un intérêt ? Cela dépend des applications. Une application de monitoring d'un réseau de senseurs peut par exemple n'avoir besoin de connaitre le temps réel qu'à la dernière minute près, si ces senseurs monitorent des phénomènes transitoires qui mettent plusieurs minutes ou dizaines de minutes. Une application OLAP peut ne servir à faire des statistiques que pour des périodes allant de 1j à des années. un retard qui se compte en secondes n'a alors aucune importance. A l'inverse, la plupart des applications OLTP ne tolèrent pas de telles approximations et la consistance est primordiale.

 

Comme tous les nodes sont identiques, une ferme de serveurs d'application peut attaquer indifféremment n'importe lequel des nodes via la rowkey. Comme on le voit, l'architecture du système est telle que la scalabilité de la base est linéaire: on double les débits d'écriture et de lecture en doublant le nombre de nodes.
http://1.bp.blogspot.com/-ZFtW7MFMqZQ/TrG5ujuDGdI/AAAAAAAAAWw/heceeMD50x4/s400/scale.png

 

Autre conséquence intéressante de cette symétrie: il n'y a pas de "single point of failure". Pour cette raison associée aux possibilités étendues de réplication, Cassandra est réputé être extrêmement résistant aux pannes. Il est bien adapté pour des applications où la disponibilité est primordiale.

 

Les restrictions par rapport à un SGBDR
Le revers de la médaille est que le modèle de données est relativement inflexible et nécessite d'être organisé au préalable afin d'optimiser les requêtes qui vont être faites. On voit que si le langage CQL est en surface réminiscent du SQL, ce qui se cache derrière est absolument sans comparaison, et la conception d'un modèle de données performant nécessite de comprendre dans le détail comment fonctionne Cassandra. De plus, la nature distribuée et décentralisée du système rend très difficiles des opérations considérées comme des acquis dans les SGBDR. Ainsi, Cassandra n'offre pas de jointures (c'est en partie compensé par la dénormalisation), mais pas non plus GROUP BY. La contrainte d'unicité sur les rows n'xiste pas pour des raisons évidentes de performance, mais peut être simulée par l'adjonction d'un UUID à la rowkey. L'utilisation de DISTINCT est très restreinte, et SORT BY doit dans la mesure du possible être pris en compte dès la modélisation. Enfin, il n'y a pas d'opérations d'aggrégation, bien que ça soit à l'étude. Il est à noter toutefois que le sharding de bases MySQL impose généralement le même genre de restrictions, tout en ayant en sus les contraintes liées à la réplication et à la durabilité d'une base distribuée, contraintes que Cassandra résout élégamment. Le sharding de bases MySQL privilégie la consistance (au sens CAP) au détriment de la durabilité. Cela équivaut à un facteur de réplication égal à 1.

 

Détails d'implémentation
L'implémentation de Cassandra inclut une conception et des algorithmes très sophistiqués. En vrac, ConcurrentSkipList, LZ4 ou Snappy pour la compression, Paxos pour les transactions légères, LMAX disruptor, MurMur3, Bloom filter, Snap tree, Merkle tree, protocole Gossip (détection de panne), I/O non bloquantes, architecture SEDA, n'en jetez plus. Pour étudier dans le détail le fonctionnement dynamique de Cassandra, ce blog post est technique mais excellent.
La base est optimisée pour l'écriture. Les données sont écrites d'abord sur un fichier de commit log, puis dans une memtable, qui est ensuite flushée sur disque dans une SSTable quand elle est pleine. Toutes les écritures sont séquentielles, même pour les mutations de données. Ces dernières sont timestampées, mais il n'y a pas de notion d'historisation. Pour une suppression, on leur assigne une valeur spéciale, la tombstone (pierre tombale), et régulièrement, une phase de compaction des SSTables supprime physiquement les valeurs en tâche de fond via un GC.

 

J'espère par ce petit tour d'horizon avoir fait comprendre que Cassandra est un produit sérieux et très avancé, dont l'usage est réservé aux applications non transactionnelles pour lesquelles la scalabilité et la disponibilité sont importantes.

 

Ressources:
https://blogs.atlassian.com/2013/09 [...] cassandra/
http://horicky.blogspot.fr/2010/10 [...] hbase.html
http://highlyscalable.wordpress.co [...] databases/


Message édité par el muchacho le 03-02-2014 à 21:31:03

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2218295
youmoussa
Ecrou-vis
Posté le 01-02-2014 à 02:25:03  profilanswer
 

Citation :

faire de la réplication en temps réel entre plusieurs data centers ou entre un data center et un cloud


 
C'est quoi la différence entre les 2 ?


---------------
Galerie HFR - Photoblog San Francisco - American Cars Photos
n°2218296
el muchach​o
Comfortably Numb
Posté le 01-02-2014 à 03:45:24  profilanswer
 

J'allais te répondre que dans le premier cas, on a le contrôle des nodes, pas dans l'autre, mais effectivement, dans le cas d'une BD, il n'y en a pas vraiment, il faut avoir le contrôle des nodes.


Message édité par el muchacho le 01-02-2014 à 03:54:13

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2218345
el muchach​o
Comfortably Numb
Posté le 02-02-2014 à 11:50:20  profilanswer
 

Et encore un excellent post d'Ilya Katsov: http://highlyscalable.wordpress.co [...] rocessing/
Le sujet cette fois-ci est le traitement en temps réel distribué.


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Précédente

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  Le NoSQL: MongoDB, Redis, Cassandra, HBase, etc

 

Sujets relatifs
php + mongoDBConférence MongoDB Paris le 23 Mars
[NoSQL] MongoDB et l'aggrégation 
Plus de sujets relatifs à : Le NoSQL: MongoDB, Redis, Cassandra, HBase, etc


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR