Soru Dizinlenmiş alan ile MongoDB düzenli ifade


MongoDB kullanarak ilk uygulamamı oluşturuyordum. Bir alan için dizin oluşturuldu ve bir kabukta başlatılan $ regex param ile bir bulma sorgusu denendi

> db.foo.find({A:{$regex:'BLABLA!25500[0-9]'}}).explain()
{
        "cursor" : "BtreeCursor A_1 multi",
        "nscanned" : 500001,
        "nscannedObjects" : 10,
        "n" : 10,
        "millis" : 956,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "isMultiKey" : false,
        "indexOnly" : false,
        "indexBounds" : {
                "A" : [
                        [
                                "",
                                {

                                }
                        ],
                        [
                                /BLABLA!25500[0-9]/,
                                /BLABLA!25500[0-9]/
                        ]
                ]
        }
}

Bu çok garip, çünkü aynı sorguyu başlattığımda, ancak koleksiyonda bir dizin olmadan, performans çok daha iyi.

> db.foo.find({A:{$regex:'BLABLA!25500[0-9]'}}).explain()
{
        "cursor" : "BasicCursor",
        "nscanned" : 500002,
        "nscannedObjects" : 500002,
        "n" : 10,
        "millis" : 531,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "isMultiKey" : false,
        "indexOnly" : false,
        "indexBounds" : {

        }
}

Açıkçası, regex içermeyen bir alanın aranması çok daha hızlı çalışıyor (yani, belgeyi sabit alanla arıyor), fakat bu tür davranışların nedeni ile gerçekten ilgileniyorum.


22
2017-11-12 19:51


Menşei


Endeks ile yavaşlamaya ne sebep olduğunu bilmiyoruz, ama eğer indeksi kullanmak için regex istiyorsanız ^BLABLA!25500[0-9] mongodb'un ilk karakterlerin ne olduğunu bilmesine izin vermek (eğer sizin usecase'inize uyuyorsa). - Lycha
İşe yarıyor! Nasıl unutabilirdim ... şimdi sadece 49 milis sürer. Teşekkürler! Ama indeksle neden daha yavaş olduğunu bilmiyorum, eğer mongo endeksi kullanamayacağını ve koleksiyonda tam araştırmayı işleyemediğini anlarsa ... İndeks nasıl umurunda? ... - Eramir
@Lycha: Bu sadece yaptığınız bir varsayımdır ve yanlıştır: düzenli bir alanda bir normal ifadenin yapılması, bu indeksin (koleksiyondaki her bir dokümanı taramayacaktır), regex ifadesi hakkında bir şey söylemese bile önek (normal ifade / .*whatever.*/ gibi bir şey olsa bile) - Shivan Dragon
@AndreiBodnarescu Bunu nerede okudunuz? Performansa dayanarak tavsiyem doğru görünüyor. Bu mongodb sitesinden alıntıdır "Basit önek sorguları için (ayrıca köklü regexps denir) / ^ önek / gibi, veritabanı kullanılabilir ve uygun olduğunda bir dizin kullanacaktır". Buna dayanarak, yalnızca önceden sabitlenmiş regex'ler için dizin kullanır. - Lycha
Belgelerinde bunu özlemiş olmalıyım, ancak bazı temel testler yapmak, temel (metin gibi) dizine eklenmiş bir alan için, bir önek belirtip belirtmemeniz olsa bile, normal ifadelerin her zaman indeks kullanacağını gösterir. Bu, nokta notasyonu ($ elemMatch değil) kullandığınız sürece gömülü diziler alanları için de geçerlidir. Temel olarak, aramalarda dizin kullanımı söz konusu olduğunda, önek içeren bir regex belirtirseniz veya - Shivan Dragon


Cevaplar:


Buradaki performans farkının nedeni, indeks etkinken, sorgunuzun endeksi (belleğe yük) geçmesi, ardından da eşleştirilecek belgeleri de belleğe yüklemesidir. Önek sorgusunu kullanmadığınız için dizindeki tüm değerler taranacak ve normal ifadeye göre test edilecektir. Çok verimli değil.

İndeksi kaldırdığınızda, sadece bir tablo taraması yapıyor ve orada düzenli ifadeyi eşleştiriyorsunuz - temel olarak ilkinden biraz daha basit olan şeyleri basitleştirdiniz.

Eğer endeksli versiyonu daha hızlı olsaydınız kapalı dizin sorgusuAyrıca, bu bileşik bir indeks olsaydı daha hızlı olurdu ve bunu başka bir alanın kriterleri ile birleştirmeniz gerekiyordu.

Bir önek sorgusu kullandığınızda, sadece bir dizin kullanır, ancak dizini verimli kullanırsınız, bu anahtardır ve dolayısıyla gerçek performans kazanımlarını görürsünüz.


13
2017-07-06 20:04