0

このクエリを試しました

db.tablebusiness.find({ "LongitudeLatitude" : { "$nearSphere" : [106.772835, -6.186753], "$maxDistance" : 0.053980478460939611 }, "Prominent" : { "$gte" : 15 }, "indexContents" : { "$all" : [/^warung/, /^nasi/] } }).skip(20).limit(20);

これは、Amazon EC2 インスタンス micro からのログが言うことです

Fri Sep 07 03:21:08 [clientcursormon] mem (MB) res:312 virt:12424 mapped:6094
Fri Sep 07 03:21:43 [conn52] query isikotacobacoba.tablebusiness query: { $query: { LongitudeLatitude: { $nearSphere: [ 106.772835, -6.186753 ], $maxDistance: 0.05398047846093961 }, Prominent: { $gte: 15 }, indexContents: { $all: [ /^warung/, /^nasi/ ] } }, $hint: { LongitudeLatitude: "2d", Prominent: -1, indexContents: 1 } } ntoreturn:20 ntoskip:20 nscanned:40 nreturned:20 reslen:1141 567133ms
Fri Sep 07 03:22:04 [DataFileSync] flushing mmap took 15ms  for 9 files

8 GB のメモリを搭載した自分のローカル コンピューターを使用すると、結果は速く、つまり 2 秒です。ただし、クエリを制限しないと、結果は依然として遅いです。例えば:

db.tablebusiness.find({ "LongitudeLatitude" : { "$nearSphere" : [106.772835, -6.186753], "$maxDistance" : 0.053980478460939611 }, "Prominent" : { "$gte" : 15 }, "indexContents" : { "$all" : [/^warung/, /^nasi/] } }).limit(200);

非常に長い時間がかかります。さて、最も近い 200 ポイントを見つけることは難しくないはずですよね?

したがって、メモリが問題になる可能性はありません。5 km 以内に 3600 個のポイントしかない場合、200 個のポイントを見つけようとすると時間がかかります。

大規模な 8GB i5 マシンのログは次のとおりです。

Fri Sep 07 12:29:23 [conn5] command admin.$cmd command: { buildinfo: 1 } ntoreturn:1 reslen:340 0ms
Fri Sep 07 12:29:25 [conn4] query isikotacobacoba.tablebusiness query: { LongitudeLatitude: { $nearSphere: [ 106.772835, -6.186753 ], $maxDistance: 0.05398047846093961 }, Prominent: { $gte: 15 }, indexContents: { $all: [ /^warung/, /^nasi/ ] } } ntoreturn:100000 ntoskip:20 nscanned:262 nreturned:242 reslen:300329 501562ms
Fri Sep 07 12:29:34 [conn4] run command admin.$cmd { ping: 1 }

これは典型的なデータのサンプルです

{
  "_id" : "warung-nasi-nur-karomah__-6.19_106.78",
  "BuildingID" : null,
  "Title" : "Warung Nasi Nur Karomah",
  "InBuildingAddress" : null,
  "Building" : null,
  "Street" : "Jl. Arjuna Utara No.35",
  "Districts" : [],
  "City" : "Jakarta",
  "Country" : "Indonesia",
   "Checkin" : 0,
  "Note" : null,
  "PeopleCount" : 0,
  "Prominent" : 45.5,
  "CountViews" : 0,
  "StreetAdditional" : null,
  "LongitudeLatitude" : {
    "Longitude" : 106.775693893433,
    "Latitude" : -6.18759540055471
  },
  "Rating" : {
    "Stars" : 0.0,
    "Weight" : 0.0
  },
  "CurrentlyWorkedURL" : null,
  "Reviews" : [],
  "ZIP" : null,
  "Tags" : ["Restaurant"],
  "Phones" : ["081380087011"],
  "Website" : null,
  "Email" : null,
  "Price" : null,
  "openingHour" : null,
  "Promotions" : [],
  "SomethingWrong" : false,
  "BizMenus" : [],
  "Brochures" : [],
  "Aliases" : [],
  "indexContents" : ["restaura", "estauran", "staurant", "taurant", "aurant", "urant", "rant", "ant", "nt", "t", "warung", "arung", "rung", "ung", "ng", "g", "nasi", "asi", "si", "i", "nur", "ur", "r", "karomah", "aromah", "romah", "omah", "mah", "ah", "h"]
}

これは私のホーム マシンでの同じクエリのログです (Amazon ec2 インスタンス マイクロではありません)。

Fri Sep 07 10:52:28 [conn1] query isikotacobacoba.tablebusiness query: { LongitudeLatitude: { $nearSphere: [ 106.772835, -6.186753 ], $maxDistance: 0.05398047846093961 }, Prominent: { $gte: 15 }, indexContents: { $all: [ /^warung/, /^nasi/ ] } } ntoreturn:50 nscanned:50 nreturned:50 reslen:62090 2048ms

自宅のコンピューターよりも amazonec2 が遅いことは理解しています

インデックスは

  db.tablebusiness.getIndexes();
    [
            {
                    "v" : 1,
                    "key" : {
                            "_id" : 1
                    },
                    "ns" : "isikotacobacoba.tablebusiness",
                    "name" : "_id_"
            },
            {
                    "v" : 1,
                    "key" : {
                            "LongitudeLatitude" : "2d",
                            "Prominent" : -1,
                            "indexContents" : 1
                    },
                    "ns" : "isikotacobacoba.tablebusiness",
                    "name" : "LongLat_Prominent_indexContents",
                    "dropDups" : false,
                    "background" : false
            },
            {
                    "v" : 1,
                    "key" : {
                            "LongitudeLatitude" : "2d",
                            "Prominent" : -1
                    },
                    "ns" : "isikotacobacoba.tablebusiness",
                    "name" : "LongLat_Prominent",
                    "dropDups" : false,
                    "background" : false
            }
    ]

ご覧のとおり、適切にインデックスされています

考えられる問題の 1 つは、Amazon マイクロ インスタンスのメモリ不足です。

ただし、nearSphere は 0.053980478460939611 度 (約 5 km) に制限されます。インデックスがなくても、テーブル スキャンだけでも、それほど多くのメモリは必要ありません。

本当の問題は何ですか?

これがmongodbのビルド情報です

>  db.runCommand("buildInfo")
{
        "version" : "2.0.7",
        "gitVersion" : "875033920e8869d284f32119413543fa475227bf",
        "sysInfo" : "windows sys.getwindowsversion(major=6, minor=1, build=7601,
 platform=2, service_pack='Service Pack 1') BOOST_LIB_VERSION=1_42",
        "versionArray" : [
                2,
                0,
                7,
                0
        ],
        "bits" : 64,
        "debug" : false,
        "maxBsonObjectSize" : 16777216,
        "ok" : 1
}
>

さらにいくつかのテストを行いました:

db.tablebusiness.find({ "経度緯度" : { "$nearSphere" : [106.772835, -6.186753], "$maxDistance" : 0.053980478460939611 } }).skip(20).limit(100000); 「のみ」の 3600 ドキュメントを返します。実際には500秒かかります。

mongodb がインデックスを使用していない場合でも、3600 のドキュメントをスキャンし、距離を計算してからソートするのに、マイクロ マシンでもそれほど時間はかかりません。

ここで、$nearsphere を使用せずに $near を使用すると、状況は良くなりますが、それでも残念です

Fri Sep 07 04:49:38 [conn61] query isikotacobacoba.tablebusiness query: { LongitudeLatitude: { $near: [ 106.772835, -6.186753 ], $maxDistance: 0.05398047846093961 }, Prominent: { $gte: 15.0 }, indexContents: { $all: [ /^warung/, /^nasi/ ] } } ntoreturn:20 ntoskip:20 nscanned:32 nreturned:12 reslen:14984 49636ms
Fri Sep 07 04:49:38 [conn61] run command admin.$cmd { replSetGetStatus: 1, forShell: 1 }

Explain() Amazon EC2 インスタンス Micro から

{
        "cursor" : "GeoSearchCursor",
        "nscanned" : 40,
        "nscannedObjects" : 40,
        "n" : 20,
        "millis" : 349182,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "isMultiKey" : false,
        "indexOnly" : false,
        "indexBounds" : {

        }
}

同じクエリで My localhost ホーム コンピューターから Explain()

{
        "cursor" : "GeoSearchCursor",
        "nscanned" : 40,
        "nscannedObjects" : 40,
        "n" : 20,
        "millis" : 4849,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "isMultiKey" : false,
        "indexOnly" : false,
        "indexBounds" : {

        }
}

これはランダムに発生します。ほとんどの場合、それは猛烈な速さです。遅いときは地獄のように遅い。

4

2 に答える 2

3

EC2 マイクロ インスタンスには 640MB の RAM しかなく、ローカル ストレージはありません。メモリに収まらない大きなワーキング セットがある場合、多くのページ フォールトが発生し、ネットワーク経由でデータをページングする必要があるため、さらにコストがかかります。

これをテストするには、クエリの実行中にmongostatを実行し、多くのページ フォールトがあるかどうかを確認します。その場合は、より多くの RAM とローカル ストレージを備えたより大きな EC2 インスタンスにアップグレードすると、問題が解決する可能性があります。

于 2012-09-07T05:06:40.233 に答える
0

ここで同様の質問をしましたなぜ $in は $all よりもはるかに高速ですか?

$all に影響を与える mongodb のバグが判明しました。それが主な問題です。ハードウェアを変更すると改善されますが、$all をまったく使用しないほどではありません。

于 2012-09-24T15:22:23.993 に答える