mongodb tips – maxTimeMS()

สำหรับเว็บไซต์ที่มี traffic ค่อนข้างสูง และมีการ query data ที่(อาจ)ใช้เวลานาน user คงไม่รอให้หน้าเว็บโหลดนานเป็นหลักนาทีๆ เพื่อให้ได้ผลลัพธ์ออกมา ดังนั้น query ที่นานเกินเวลาที่ user จะยอมรับได้ เราควรกำจัดมันทิ้งเสีย

หากไม่ตัด query ทิ้ง ก็จะทำให้เป็น load ที่ฝั่ง server สะสม มีผลทั้ง I/O, memory และ CPU time และอาจทำให้ server ไม่ตอบสนองได้หากสะสมเกินค่า config ที่ตั้งไว้ หรือเกิน capacity ที่ resource เครื่องจะรับได้

เราสามารถใช้เทคนิคง่ายๆ ในการกำหนดเวลาสูงสุดที่จะให้ query รันได้ ซึ่งหากเกินค่านี้ ตัว client จะส่ง exception ออกมาและตัดการทำงานให้โดยอัตโนมัติ คือการใช้ cursor.maxTimeMS() เช่น

db.traffic.find({"location.country": "CN"}).maxTimeMS(5000)

กรณีนี้ หาก query ทำงานไม่เสร็จภายในเวลา 5 วินาที ก็จะได้ exception กลับออกมาประมาณนี้

Error: error: {
"operationTime" : Timestamp(1567912754, 5),
"ok" : 0,
"errmsg" : "Executor error during find command :: caused by :: operation exceeded time limit",
"code" : 50,
"codeName" : "MaxTimeMSExpired"
}

การทำ aggregation ก็สามารถระบุ maxTimeMS ได้เช่นกัน โดยระบุไว้ใน options

db.traffic.aggregate([
    {$match: {
        "location.country": "CN"
    }}
    , {$limit: 50}
], {
    maxTimeMS: 5000
})

ตัวอย่างการใส่ options ใน PHP (Yii2 framework)

$collection = Yii::$app->mongodb->getCollection('traffic');
 try {
     $result = $collection->aggregate([
         ['$match' => [
             'location.country' => 'CN'
         ]],
        ['$limit' => 50]
     ],
     ['maxTimeMS' => 5000]);
 }
 catch (\yii\mongodb\Exception $ex) {
     echo "Time out exceed";
 }

Leave a Reply

Your email address will not be published. Required fields are marked *