Firebase에서 index를 붙이면 얼마나 정렬이 빨라지는지

11855 단어 FirebaseObjective-C
데이터베이스에 포함된 요소를 어떤 숫자로 정렬하여 얻고 싶어지는 경우가 많습니다.
그런 것을 MySQL 라든지로 하는 경우, 그 요소에 index라고 하는 것을 붙여, 소트를 고속화하거나 하는 것입니다만, Firebase로 어째서 DB 조작을 즐기고 있는 프런트 엔드의 사람(나도 그런 것입니다 가) 그렇게 잘 모르겠어요.
그러나, Firebase에도 index 기능은 제대로 있어, 게다가 상당히 좋은 느낌입니다만, 너무 이 근처의 일을 쓰고 있는 일본어 문헌이 없었기 때문에 써 보겠습니다.

우선, index에 의한 고속화를 실감하기 위해서는 그만한 양의 데이터가 필요할까 생각하기 때문에, js로 아래와 같은 코드를 써, 뭔가 오브젝트를 20000개 정도 만들 것입니다.

bigdata.js
var MAX_NUM = 20000;
for(var i=0; i<MAX_NUM; i++){
    //各オブジェクトの名前を適当にランダムで生成
    var _name = Math.random().toString(36).slice(-16);
    //数値をランダムで生成
    var _num = Math.floor(Math.random()*1000000);

    //追加するオブジェクトのデータを用意する
    var postData = {
        name: _name,
        num: _num
    };
    //オブジェクトを追加する
    var newPostKey = firebase.database().ref().child('Objects').push().key;
    var updates = {};
    updates['/Objects/' + newPostKey] = postData;
    firebase.database().ref().update(updates, function(error) {
        if (!error) {
            _firebase.raiseEvent('dataIncreaseComplete',[]);
        }
    });
}

이런 느낌의 코드를 실행하면 아래와 같은 느낌으로 대량으로 랜덤한 수치가 붙은 데이터가 생성됩니다. 이것으로 준비 완료입니다.



데이터를 취득하는 클라이언트측은 무엇으로 써도 좋지만, 이번은 Objective-C로 실험합니다.

아래의 순서로 세팅을 하면서,
Firebase를 iOS 프로젝트에 추가

포드는
pod 'Firebase/Core'
pod 'Firebase/Database'

의 2개를 넣어 둡니다.

그리고, 우선, index라든지 아무것도 설정하지 않고 아래와 같이 달려 보겠습니다.
이 시점의 rule은 아래와 같은 느낌입니다.
{
    "rules": {
        "Objects": {
            ".read": true,
            ".write": true
        }
    }
}

오브젝트 수는 20,000개. 처음 500개만 가져옵니다.

ViewController.m
#import "ViewController.h"
@import Firebase;
@import FirebaseDatabase;

@interface ViewController ()

@end

@implementation ViewController{
    FIRDatabaseReference *rootRef;
    NSDate *startDate;
    NSDate *endDate;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    rootRef= [[FIRDatabase database] reference];
    // Do any additional setup after loading the view, typically from a nib.
    FIRDatabaseReference *objects = [rootRef child: @"Objects"];

    startDate = [NSDate date];

    [[objects queryOrderedByChild:@"num"] queryLimitedToFirst:500] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot){

        endDate = [NSDate date];
        NSTimeInterval interval = [endDate timeIntervalSinceDate:startDate];
        NSLog([NSString stringWithFormat:@"処理時間 : ミリ秒 : %f",interval]);
        //データの中身を確認する場合、下記を実行
        /*
        for (FIRDataSnapshot* childSnap in snapshot.children) {
            NSLog(@"%@", childSnap.value[@"name"]);
            NSLog(@"%@", childSnap.value[@"num"]);
        }
        */
    }withCancelBlock:^(NSError *error){
    }];

}

- (NSString*)getDateString:(NSDate*)date
{
    NSDateFormatter *dateFormatter = [NSDateFormatter new];
    [dateFormatter setDateFormat:@"yyyy/MM/dd HH:mm:ss.SSS"];
    NSString *dateString = [dateFormatter stringFromDate:date];
    return dateString;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}


@end

시간을 측정하는 사람은 여기에서 빌렸습니다.
5.973116초에 처리가 종료되었습니다. 몇 번 해도 이 근처.
로그에서 내용을 확인하면 제대로 num이 작은 녀석부터 차례로 내보내지고 있지만 나름대로 느립니다.

그래서 이번에는 index를 붙이면 얼마나 빨라지는지 살펴 보겠습니다.

이번에는 "num"의 값으로 정렬하기 때문에 Firebase 콘솔에서 rule을 아래와 같은 느낌으로합니다.
{
    "rules": {
        "Objects": {
            ".read": true,
            ".write": true,
            ".indexOn": ["num"]
        }
    }
}

이것만으로 "num"에 대한 index가 붙여졌습니다.
클라이언트 측 코드는 변경할 필요가 없습니다.
이제 다시 Firebase의 응답을 측정해 보겠습니다.

0.659976초. 훌륭합니다. 빠르다.

index라는 개념은 데이터베이스를 평상시에서 만지고 있는 사람에게는 당연한 개념입니다만, 특히 Firebase는 백엔드에 대해서 별로 잘 모르더라도 프런트의 김으로 어떻게 하기 위한 구조이므로, 상당히 모르는 사람이 많은 것이 아닐까 생각합니다.
그렇다고는 해도, 다시 시도해 보면 알기 쉽고 고속이었으므로, 이런 일을 할 때는, index를 붙이지 않는 손은 없을까 생각했습니다.

코드는 아래와 같습니다.

데이터 증식하는 사람
Firebase-dataIncrement

iOS-app
Firebase-indextest

좋은 웹페이지 즐겨찾기