6 votes

MongoDB, requêtes complexes et performances

Back-Story

Sur un projet en cours, j'utilise MySQL et SQLite en combinaison l'un avec l'autre. Je donne actuellement à chaque utilisateur sa propre base de données SQLite pour contourner la limite de 1 Go de bases de données MySQL de mon fournisseur. Cela a bien fonctionné et les performances sont bonnes, mais je sais pertinemment que la maintenance continue de ces bases de données de fichiers plats sera un cauchemar à l'avenir.

SQLite est étonnamment puissant, et supporte des requêtes SQL assez complexes. Cependant, je me tourne vers MongoDB pour embarquer un peu de NoSQL pour les données en vrac de mes utilisateurs. Chaque utilisateur pourrait générer 60 000 lignes ou plus. Avec un nombre d'utilisateurs en constante augmentation, je dois m'inquiéter des performances à venir.

-

Complexité

Mon souci avec MongoDB et les autres bases de données NoSQL est qu'elles semblent plus limitées dans le type d'opérations de requête qu'elles supportent. Ce n'est pas un problème si vous n'avez besoin que de requêtes en masse simples et directes, mais je dois effectuer des jointures et des filtrages plus complexes (unions, sensibilité à la casse, regroupements, jointures occasionnelles, etc...).

Ma requête d'exemple tente de sélectionner une liste de pistes par artiste. Le problème principal est que ces noms d'artistes peut ne pas correspondre . Par exemple, certaines personnes étiquettent comme "Un jour à se souvenir" et d'autres comme "Un jour". A Se souvenir". Dans le cas d'une requête sensible à la casse, cela entraîne la remontée de plusieurs enregistrements qui sont "différents" mais qui correspondent en réalité à la même chose. En général, je coupe les champs et je les abaisse par LOWER() pour les regrouper correctement.

-

Performance

J'ai créé deux nouvelles bases de données sur ma machine locale. Une pour MongoDB, et une pour MySQL. Je leur parle avec PHP puisque c'est ce que mon résultat final devra utiliser. Chaque base de données ne contient qu'environ 9 000 enregistrements, ce qui n'est pas très important à ce stade.

J'ai effectué quelques tests sur ma machine et j'ai obtenu des résultats décevants pour MongoDB. Considérons ces trois requêtes...

#1 - MongoDB : ~14ms, résultats incorrects

$query = array('artist' => 'A Day to Remember');
$cursor = $collection->find($query);
foreach ($cursor as $row) {
    echo $row['artist'] . ' - ' . $row['album'] . ' - #'. $row['track'] . ' ' . $row['title'] . "\r\n";
}

#2 - MongoDB : ~170ms, résultats corrects

$query = array('$where' => "this.artist.toLowerCase() == 'a day to remember'");
$cursor = $collection->find($query);
foreach ($cursor as $row) {
    echo $row['artist'] . ' - ' . $row['album'] . ' - #'. $row['track'] . ' ' . $row['title'] . "\r\n";
}

#3 - MySQL : ~18ms, résultats corrects

$sql = "select artist, album, track, title from radio_files where lower(artist) = 'a day to remember'";
$stmt = $mysqldb->prepare($sql);
$stmt->execute();
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
    echo $row['artist'] . ' - ' . $row['album'] . ' - #'. $row['track'] . ' ' . $row['title'] . "\r\n";
}

-

Discussion

Peut-être que je ne demande pas correctement le numéro 2, mais regardez comment le moteur de recherche Javascript le détruit. . Il n'y a même pas beaucoup d'enregistrements à traiter ici au total : un peu moins de 9 000 dans toute la base de données.

Ma principale question est la suivante Qu'est-ce qui sera le plus fiable et le plus performant au final, tout en répondant à mes besoins ? Comme le nombre d'utilisateurs de mon projet augmente, je cherche à quitter mon serveur limité et à obtenir quelque chose de dédié de toute façon. Avec ma propre installation MySQL, je devrais être capable de maintenir mes propres grandes tables MyISAM avec peu de données relationnelles et une indexation appropriée.

Mais avec des millions d'enregistrements dans la base de données, qu'advient-il des performances de MySQL ? Nous vous encourageons à nous faire part de vos réflexions, commentaires et discussions générales sur le sujet. Merci !

7voto

Maxence Points 5619

Essayez avec une expression régulière :

$regex = new MongoRegex('/^' . preg_quote('a day to remember'). '$/i');
$query = array('artist' => $regex);
$cursor = $collection->find($query);

6voto

TTT Points 1894

Vous devez stocker une valeur deux fois si vous voulez effectuer une recherche insensible à la casse sur cette valeur dans Mongodb. Une fois normalement et une fois en minuscules pour l'indexation et la recherche.

Mongodb possède un langage de requête riche (comparé aux autres systèmes nosql) et vous pouvez indexer chaque (combinaison) de colonnes. Je trouve cependant que mapreduce est lent, mais tant que vous pouvez résoudre votre problème sans mapreduce, tout va bien.

4voto

Daniel Vassallo Points 142049

Les différentes solutions NoSQL diffèrent entre elles bien plus que les bases de données SQL traditionnelles, mais MongoDB est en fait l'une des solutions les plus riches en fonctionnalités, notamment en ce qui concerne la complexité des requêtes.

Toutefois, vous ne devez pas opter aveuglément pour une solution NoSQL simplement parce que vous attendez 60 000 lignes par utilisateur. MySQL et les autres SGBD relationnels populaires peuvent gérer des milliards de lignes sans problème.

Les bases de données relationnelles sont dotées de nombreuses fonctionnalités importantes ( ACID garanties et requêtes complexes par exemple), et si vous avez besoin de ces fonctionnalités, vous pouvez tout aussi bien utiliser une base de données SQL. Le NoSQL est généralement un compromis entre certaines de ces fonctionnalités (ou toutes) et la facilité de l'extensibilité horizontale. Si vous pouvez espérer gérer le problème d'évolutivité de votre système en utilisant un SGBD relationnel, alors j'envisagerais sérieusement de m'en tenir à SQL.

Je donne actuellement à chaque utilisateur sa propre base de données SQLite pour contourner la limite de 1 Go de bases de données MySQL de mon fournisseur.

Vous pouvez également envisager de changer de fournisseur. Un hébergeur qui applique de telles limites finira probablement par vous limiter d'une autre manière.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X