Maison > Questions et réponses > le corps du texte
1、文档结构示例
{
_id: xxxx,
user: 'xiaoming',
level: 5,
from: 'iPhone',
info: 'something wrong'
}
2、场景:user为'xiaoming'的文档有六七百万条
3、问题:怎么提升aggregate+group+sum速度
aggregate([
{$match:{user: 'xiaoming', info:{$regex:'wrong'}}},
{$group:{_id:null, count:{$sum:1}}}
])
用上面这个来统计xiaoming带有wrong的文档数量,结果
{"_id": null, "count": 2299999 }
耗时30s-40s。user、info、user+info三种索引都尝试过,速度都没有提升
baidu、google查到‘带条件计数慢无解’
怎么提升效率,10s以内能实现吗
PHP中文网2017-05-02 09:22:16
La première chose à noter est que pour les opérations de type OLAP, les attentes ne doivent pas être trop élevées. Après tout, il s'agit d'une opération portant sur de grandes quantités de données. Les E/S à elles seules vont bien au-delà de l'opération OLTP habituelle, il est donc irréaliste et dénué de sens d'exiger la vitesse et la simultanéité des opérations OLTP. Mais cela ne veut pas dire qu’il n’y a aucune place à l’optimisation.
Commençons par l’index. Combien de temps faut-il pour trouver 6 millions {user: "xiaoming"}
éléments sans index ? Analyse de table complèteCOLLSCAN
Trouver 6 millions de données à partir de 7 millions de données et trouver 6 millions de données à partir de 100 millions de données sont évidemment deux concepts différents. Hit index IXSCAN
, cette différence sera bien moindre et presque négligeable. Vous avez donc tort de dire {user: 1}
que cet index n'a aucun effet. C'est peut-être simplement parce que la quantité de données dans la collection est trop petite pour voir la différence. À propos, il convient de mentionner que pour voir s’il y a une différence d’efficacité, il faut examiner le plan d’exécution et non le temps d’exécution, car celui-ci est inexact.
Avec l'index user
, il y a encore 6 millions de résultats, et la partie restante est regex
ne peut pas atteindre l'index, cela n'a donc aucun sens qu'il y ait un index pour regex
ou non. Après avoir trouvé 6 millions de données, il y a une autre info
opération sur 6 millions de données. La seule chose qui peut être utile pour cette opération est filter
, mais l'indexation en texte intégral ne peut pas remplacer complètement les expressions régulières. Vous devez lire la documentation pour des problèmes spécifiques. Si l'indexation en texte intégral est réalisable, un index composite peut être établi : 全文索引
db.coll.createIndex({
user: 1,
info: "text"
});
La requête correspondante doit être modifiée en :
db.coll.aggregate([
{$match:{user: 'xiaoming', $text: { $search: "wrong" }}},
{$group:{_id:null, count:{$sum:1}}}
])
Pour une introduction à l'index composite en texte intégral, veuillez vous référer ici. Certaines limitations doivent encore être notées. Après cette optimisation, il est prévu que le temps puisse être réduit à moins de 20 secondes sous le même matériel, ce qui est encore loin des 10 secondes souhaitées. Comme mentionné au début, nous ne pouvons pas avoir des attentes aussi élevées envers OLAP. Si vous avez vraiment ce besoin, vous devriez partir de la source et considérer :
est mis à jour ou inséré info
ou
某草草2017-05-02 09:22:16
Je ne sais pas, mais serait-ce mieux si cela pouvait être divisé en deux matches ? .
Similaire à
aggregate([
{$match:{user: 'xiaoming'}},
{$match:{info: /wrong/}},
{$group:{_id:null, count:{$sum:1}}}
])
La chose principale à mon avis, c'est de prendre du temps.
S'il existe un index, indexez l'utilisateur.
给我你的怀抱2017-05-02 09:22:16
L'exigence en temps réel n'est pas élevée et peut être comptée régulièrement et mise en cache