Program Club

데이터 가져 오기시 Firestore 성능 저하 문제

proclub 2020. 11. 18. 21:41
반응형

데이터 가져 오기시 Firestore 성능 저하 문제


1/10 비율의 실시간 데이터베이스에 비해 문서에 저장된 기본 데이터를 검색하는 동안 Firestore에서 성능 저하 문제가 있습니다.

Firestore를 사용하면 첫 번째 호출에서 평균 3000ms가 걸립니다.

 this.db.collection(‘testCol’)
   .doc(‘testDoc’)
   .valueChanges().forEach((data) => {
     console.log(data);//3000 ms later
 });

실시간 데이터베이스를 사용하면 첫 번째 호출에서 평균 300ms가 걸립니다.

 this.db.database.ref(‘/test’).once(‘value’).then(data => {
     console.log(data); //300ms later
 });

다음은 네트워크 콘솔의 스크린 샷입니다.

Firestore 성능 저하 문제 데이터 가져 오기

AngularFire2 v5.0 rc.2와 함께 Javascript SDK v4.50을 실행하고 있습니다.

누구든지이 문제를 경험 했습니까?


업데이트 : 2018 년 2 월 12 일-iOS Firestore SDK v0.10.0

다른 댓글 작성자와 마찬가지로 첫 번째 get 요청에서 응답 속도가 느리다는 것을 발견했습니다 (이후 요청은 ~ 100ms 소요). 저에게는 30 대만큼 나쁘지는 않지만 연결 상태가 좋으면 2-3 초 정도가 될 수 있습니다. 앱이 시작될 때 나쁜 사용자 경험을 제공하기에 충분합니다.

Firebase는이 '콜드 스타트'문제를 알고 있으며 이에 대한 장기적인 수정 작업을 진행 중이라고 조언했습니다. 안타깝게도 ETA는 없습니다. 연결 상태가 좋지 않은 경우 요청이 캐시에서 읽기로 결정되기까지 시간이 오래 걸릴 수 있다는 것은 별도의 문제라고 생각합니다.

Firebase가 이러한 모든 문제를 해결하는 동안 저는 Firebase 의 온라인 / 오프라인 상태를 수동으로 제어하기 위해 새로운 disableNetwork()enableNetwork()메서드 (Firestore v0.10.0에서 사용 가능)를 사용하기 시작했습니다 . 나는 것으로 했어하지만 매우 특정 시나리오에서 충돌이 발생할 수있는 경우 FireStore 버그 거기에 나는, 내 코드에서 사용할 경우주의하십시오.


업데이트 : 2017 년 11 월 15 일-iOS Firestore SDK v0.9.2

성능 저하 문제가 해결 된 것 같습니다. 아래에 설명 된 테스트를 다시 실행했으며 Firestore가 100 개의 문서를 반환하는 데 걸리는 시간은 이제 일관되게 약 100ms 인 것 같습니다.

이것이 최신 SDK v0.9.2의 수정인지 아니면 백엔드 수정 (또는 둘 다)인지 확실하지 않지만 모두가 Firebase 포드를 업데이트하는 것이 좋습니다. 내 앱은 실시간 DB에서와 비슷하게 눈에 띄게 더 반응이 좋습니다.


또한 특히 많은 문서를 읽을 때 Firestore가 Realtime DB보다 훨씬 느리다는 것을 발견했습니다.

업데이트 된 테스트 (최신 iOS Firestore SDK v0.9.0 포함) :

RTDB와 Firestore를 모두 사용하여 iOS Swift에서 테스트 프로젝트를 설정하고 각각에 대해 100 개의 순차적 읽기 작업을 실행했습니다. RTDB의 경우 observeSingleEvent를 테스트하고 100 개의 최상위 노드 각각에서 메소드를 관찰했습니다. Firestore의 경우 TestCol 컬렉션의 100 개 문서 각각에서 getDocument 및 addSnapshotListener 메서드를 사용했습니다. 디스크 지속성을 켜고 끄면서 테스트를 실행했습니다. 각 데이터베이스의 데이터 구조를 보여주는 첨부 이미지를 참조하십시오.

동일한 장치와 안정적인 Wi-Fi 네트워크에서 각 데이터베이스에 대해 10 번 테스트를 실행했습니다. 기존 관찰자와 청취자는 각각의 새로운 실행 전에 파괴되었습니다.

실시간 DB observeSingleEvent 메소드 :

func rtdbObserveSingle() {

    let start = UInt64(floor(Date().timeIntervalSince1970 * 1000))
    print("Started reading from RTDB at: \(start)")

    for i in 1...100 {
        Database.database().reference().child(String(i)).observeSingleEvent(of: .value) { snapshot in
            let time = UInt64(floor(Date().timeIntervalSince1970 * 1000))
            let data = snapshot.value as? [String: String] ?? [:]
            print("Data: \(data). Returned at: \(time)")
        }
    }
}

실시간 DB 관찰 방법 :

func rtdbObserve() {

    let start = UInt64(floor(Date().timeIntervalSince1970 * 1000))
    print("Started reading from RTDB at: \(start)")

    for i in 1...100 {
        Database.database().reference().child(String(i)).observe(.value) { snapshot in
            let time = UInt64(floor(Date().timeIntervalSince1970 * 1000))
            let data = snapshot.value as? [String: String] ?? [:]
            print("Data: \(data). Returned at: \(time)")
        }
    }
}

Firestore getDocument 메소드 :

func fsGetDocument() {

    let start = UInt64(floor(Date().timeIntervalSince1970 * 1000))
    print("Started reading from FS at: \(start)")

    for i in 1...100 {
        Firestore.firestore().collection("TestCol").document(String(i)).getDocument() { document, error in

            let time = UInt64(floor(Date().timeIntervalSince1970 * 1000))
            guard let document = document, document.exists && error == nil else {
                print("Error: \(error?.localizedDescription ?? "nil"). Returned at: \(time)")
                return
            }
            let data = document.data() as? [String: String] ?? [:]
            print("Data: \(data). Returned at: \(time)")
        }
    }
}

Firestore addSnapshotListener 메소드 :

func fsAddSnapshotListener() {

    let start = UInt64(floor(Date().timeIntervalSince1970 * 1000))
    print("Started reading from FS at: \(start)")

    for i in 1...100 {
        Firestore.firestore().collection("TestCol").document(String(i)).addSnapshotListener() { document, error in

            let time = UInt64(floor(Date().timeIntervalSince1970 * 1000))
            guard let document = document, document.exists && error == nil else {
                print("Error: \(error?.localizedDescription ?? "nil"). Returned at: \(time)")
                return
            }
            let data = document.data() as? [String: String] ?? [:]
            print("Data: \(data). Returned at: \(time)")
        }
    }
}

각 메서드는 기본적으로 메서드가 실행을 시작할 때 밀리 초 단위로 유닉스 타임 스탬프를 인쇄하고 각 읽기 작업이 반환 될 때 다른 유닉스 타임 스탬프를 인쇄합니다. 초기 타임 스탬프와 반환 할 마지막 타임 스탬프의 차이를 확인했습니다.

결과-디스크 지속성이 비활성화 됨 :

디스크 지속성 비활성화

결과-디스크 지속성 사용 :

디스크 지속성 사용

데이터 구조 :

데이터 구조

Firestore getDocument / addSnapshotListener 메서드가 중단되면 대략 30 초의 배수 인 기간 동안 중단 된 것 같습니다. 아마도 이것이 Firebase 팀이 SDK에서 중단되는 부분을 격리하는 데 도움이 될 수 있습니까?


업데이트 날짜 2018 년 3 월 2 일

이는 알려진 문제로 보이며 Firestore의 엔지니어가 문제를 해결하기 위해 노력하고 있습니다. 이 문제에 대해 Firestore 엔지니어와 몇 차례 이메일을 교환하고 코드를 공유 한 후 이것이 오늘의 답변이었습니다.

"You are actually correct. Upon further checking, this slowness on getDocuments() API is a known behavior in Cloud Firestore beta. Our engineers are aware of this performance issue tagged as "cold starts", but don't worry as we are doing our best to improve Firestore query performance.

We are already working on a long-term fix but I can't share any timelines or specifics at the moment. While Firestore is still on beta, expect that there will be more improvements to come."

So hopefully this will get knocked out soon.


Using Swift / iOS

After dealing with this for about 3 days it seems the issue is definitely the get() ie .getDocuments and .getDocument. Things I thought were causing the extreme yet intermittent delays but don't appear to be the case:

  1. Not so great network connectivity
  2. Repeated calls via looping over .getDocument()
  3. Chaining get() calls
  4. Firestore Cold starting
  5. Fetching multiple documents (Fetching 1 small doc caused 20sec delays)
  6. Caching (I disabled offline persistence but this did nothing.)

I was able to rule all of these out as I noticed this issue didn't happen with every Firestore database call I was making. Only retrievals using get(). For kicks I replaced .getDocument with .addSnapshotListener to retrieve my data and voila. Instant retrieval each time including the first call. No cold starts. So far no issues with the .addSnapshotListener, only getDocument(s).

For now, I'm simply dropping the .getDocument() where time is of the essence and replacing it with .addSnapshotListener then using

for document in querySnapshot!.documents{
// do some magical unicorn stuff here with my document.data()
}

... in order to keep moving until this gets worked out by Firestore.


I had this issue until this morning. My Firestore query via iOS/Swift would take around 20 seconds to complete a simple, fully indexed query - with non-proportional query times for 1 item returned - all the way up to 3,000.

My solution was to disable offline data persistence. In my case, it didn't suit the needs of our Firestore database - which has large portions of its data updated every day.

iOS & Android users have this option enabled by default, whilst web users have it disabled by default. It makes Firestore seem insanely slow if you're querying a huge collection of documents. Basically it caches a copy of whichever data you're querying (and whichever collection you're querying - I believe it caches all documents within) which can lead to high Memory usage.

In my case, it caused a huge wait for every query until the device had cached the data required - hence the non-proportional query times for the increasing numbers of items to return from the exact same collection. This is because it took the same amount of time to cache the collection in each query.

Offline Data - from the Cloud Firestore Docs

I performed some benchmarking to display this effect (with offline persistence enabled) from the same queried collection, but with different amounts of items returned using the .limit parameter:

벤치 마크 Now at 100 items returned (with offline persistence disabled), my query takes less than 1 second to complete.

My Firestore query code is below:

let db = Firestore.firestore()
self.date = Date()
let ref = db.collection("collection").whereField("Int", isEqualTo: SomeInt).order(by: "AnotherInt", descending: true).limit(to: 100)
ref.getDocuments() { (querySnapshot, err) in
    if let err = err {
        print("Error getting documents: \(err)")
    } else {
        for document in querySnapshot!.documents {
            let data = document.data()
            //Do things
        }
        print("QUERY DONE")
        let currentTime = Date()
        let components = Calendar.current.dateComponents([.second], from: self.date, to: currentTime)
        let seconds = components.second!
        print("Elapsed time for Firestore query -> \(seconds)s")
        // Benchmark result
    }
}

well, from what I'm currently doing and research by using nexus 5X in emulator and real android phone Huawei P8,

Firestore와 Cloud Storage는 모두 처음 document.get () 및 first storage.getDownloadUrl ()을 수행 할 때 응답이 느려서 골칫거리입니다.

각 요청에 대해 60 초 이상의 응답을 제공합니다. 느린 응답은 실제 안드로이드 폰에서만 발생합니다. 에뮬레이터가 아닙니다. 또 다른 이상한 것. 첫 만남 후 나머지 요청은 원활합니다.

느린 응답을 만나는 간단한 코드는 다음과 같습니다.

var dbuserref = dbFireStore.collection('user').where('email','==',email);
const querySnapshot = await dbuserref.get();

var url = await defaultStorage.ref(document.data().image_path).getDownloadURL();

나는 또한 같은 것을 연구하는 링크를 찾았습니다. https://reformatcode.com/code/android/firestore-document-get-performance

참고 URL : https://stackoverflow.com/questions/46717898/firestore-slow-performance-issue-on-getting-data

반응형