TechHype
Почему запросы Firebase Cloud Firestore могут выполняться медленно?
Давайте рассмотрим некоторые наиболее распространенные причины, по которым Cloud Firestore может показаться медленным, и что вы можете сделать, чтобы их исправить.
Нам нравится впечатляющая производительность Cloud Firestore. В хранилище «производительность масштабируется исходя из результатов, а не исходя из набора данных», и, как пишут, «практически невозможно создать медленный запрос». По большей части это правда. Вы можете запрашивать наборы данных, содержащие миллиарды и миллиарды записей, и получать результаты быстрее, чем ваш пользователь отведет большой палец от экрана.
Но с учетом вышесказанного мы иногда слышим от разработчиков, что Cloud Firestore работает медленно в определенных ситуациях, и для получения результатов запроса требуется больше времени, чем ожидалось. Почему это так? Давайте рассмотрим некоторые наиболее распространенные причины, по которым Cloud Firestore может показаться медленным, и что вы можете сделать, чтобы их исправить.
Причина № 1: это данные!
Вероятно, наиболее распространенным объяснением, казалось бы, медленного запроса является то, что ваш запрос выполняется очень быстро. Но после завершения запроса нам все еще нужно перенести все эти данные на ваше устройство, и эта часть работает медленно.
Так что, да, вы можете выполнить запрос всех продавцов в вашей организации, и этот запрос будет выполняться очень быстро. Но если этот набор результатов состоит из 2000 документов сотрудников, а каждый документ содержит 75 КБ данных, вам придется подождать, пока ваше устройство загрузит 150 МБ данных, прежде чем вы сможете увидеть какие-либо результаты.
Как ускорить это
Лучший способ решить эту проблему — убедиться, что вы не передаете больше данных, чем вам нужно. Один простой вариант — добавить ограничения к вашим запросам. Если вы подозреваете, что вашему пользователю нужны только первые несколько результатов из вашего списка сотрудников, добавьте ограничение (25) в конец вашего запроса, чтобы загрузить только первый пакет данных, а затем загружать только дополнительные записи, если ваш пользователь их запрашивает. , И, эй, так получилось, у меня есть целое видео об этом!
Если вы действительно считаете необходимым запрашивать и извлекать всех 2000 сотрудников отдела продаж одновременно, другой вариант — разбить эти записи на документы, которые содержат только данные, необходимые для первоначального запроса, а затем поместить дополнительные сведения в отдельная коллекция или подборка. Эти другие документы не будут переданы при первой загрузке, но вы можете запросить их позже, когда они понадобятся вашему пользователю.
Если вы действительно считаете необходимым запрашивать и извлекать всех 2000 сотрудников отдела продаж одновременно, другой вариант — разбить эти записи на документы, которые содержат только данные, необходимые для первоначального запроса, а затем поместить дополнительные сведения в отдельная коллекция или подборка. Эти другие документы не будут переданы при первой загрузке, но вы можете запросить их позже, когда они понадобятся вашему пользователю.
Наличие документов меньшего размера также хорошо, если запроса настроен для работы в реальном времени, а документ обновлен, измененный документ отправляется на ваше устройство. Таким образом, уменьшая размер ваших документов, вы также будете передавать меньше данных каждый раз, когда в ваших слушателях происходят изменения.
Причина № 2: ваш offline кэш слишком большой
Так что автономный кеш Cloud Firestore довольно хорош. При включенном постоянстве ваше приложение «просто работает», даже если ваш пользователь входит в туннель или совершает 9-часовой перелет на самолете. Документы, считываемые в режиме онлайн, будут доступны в автономном режиме, а записи помещаются в очередь локально, пока приложение не вернется в режим онлайн. Кроме того, ваш клиентский SDK может использовать этот автономный кэш, чтобы избежать загрузки слишком большого количества данных, и он может быстрее выполнять такие действия, как запись документов. Однако Cloud Firestore не был спроектирован как «автономная первая» база данных, и поэтому в настоящее время он не оптимизирован для локальной обработки больших объемов данных.
Таким образом, хотя Cloud Firestore в облаке индексирует каждое поле в каждом документе в каждой коллекции, он (в настоящее время) не создает ни одного из этих индексов для автономного кэша. Это означает, что при запросе документов в автономном кэше Cloud Firestore необходимо распаковать каждый документ, хранящийся локально для запрашиваемой коллекции, и сравнить его с вашим запросом.
Или, другими словами, запросы в масштабах бэкэнда соответствуют размеру вашего набора результатов, но локально они в некотором роде соответствуют размеру данных в запрашиваемой коллекции.
Теперь, насколько медленные локальные запросы оказываются на практике, зависит от вашей ситуации. Я имею в виду, что мы все еще говорим о локальных, не сетевых операциях, поэтому это может (и часто) быстрее, чем совершать сетевой вызов. Но если у вас есть много данных в одной коллекции для сортировки или вы просто работаете на медленном устройстве, локальные операции в большом автономном кэше могут быть заметно медленнее.
Как это улучшить
Во-первых, следуйте рекомендациям, упомянутым в предыдущем разделе: добавьте ограничения к своим запросам, чтобы вы только извлекали данные, которые, по вашему мнению, будут нужны вашим пользователям, и рассмотрите возможность перемещения ненужных подробностей во вложенные коллекции. Кроме того, если вы следовали обсуждению «несколько подколлекций против отдельной коллекции верхнего уровня» в конце моего предыдущего поста, это было бы хорошим аргументом для структуры «несколько подколлекций», потому что кэш должен только искать данные в эти меньшие коллекции.
Во-вторых, не помещайте в кеш больше данных, чем нужно. Я видел некоторые случаи, когда разработчики делают это намеренно, запрашивая огромное количество документов при первом запуске приложения, а затем заставляя все будущие запросы к базе данных проходить через локальный кэш, обычно в схеме, чтобы уменьшить затраты на базу данных или сделать будущие звонки быстрее. Но на практике это приносит больше вреда, чем пользы.
В-третьих, подумайте об уменьшении размера автономного кэша. Размер вашего кэша по умолчанию установлен на 100 МБ на мобильных устройствах, но в некоторых ситуациях это может быть слишком много данных для вашего устройства, чтобы обрабатывать, особенно если вы в конечном итоге большую часть своих данных в одной большой коллекции. Вы можете изменить этот размер, изменив значение cacheSizeBytes в настройках Firebase, и это то, что вы можете сделать для определенных клиентов.
В-четвертых, попробуйте полностью отключить постоянное обновление и посмотрите, что произойдет. Обычно я не рекомендую такой подход — как я упоминал ранее, автономный кеш довольно хорошо работает. Но если запрос кажется медленным, и вы не знаете, почему, перезапуск приложения с отключенным постоянством может дать вам хорошее представление о том, не способствует ли ваш кеш этой проблеме.
Причина № 3: Ваш merge работает неправильно
Таким образом, зигзагообразные объединения слиянием, помимо того, что они всегда являются моим любимым именем алгоритма, очень удобны тем, что они позволяют объединять результаты из разных индексов вместе, не полагаясь на составной индекс. По сути, они делают это, переключаясь между двумя (или более) индексами, отсортированными по идентификатору документа, и находя совпадения между ними.
Но одна из особенностей зигзагообразных объединений заключается в том, что вы можете столкнуться с проблемами производительности, когда оба набора результатов достаточно велики, но перекрытие между ними невелико. Например, представьте запрос в приложении для обзора ресторанов, в котором вы искали дорогие рестораны, которые также предлагали встречные услуги.
restaurant.where (‘price’, ‘==’, ‘$$$$’). where (‘orderAtCounter’, ‘==’, ‘true’)
Хотя обе эти группы могут быть довольно большими, между ними, вероятно, очень мало совпадений. Наше объединение слияний должно было бы сделать много поиска, чтобы дать вам результаты, которые вы хотите.
Поэтому, если вы заметили, что большинство ваших запросов кажутся быстрыми, но конкретные запросы выполняются медленно, когда вы выполняете их для нескольких полей одновременно, вы можете столкнуться с этой ситуацией.
Как это исправить
Если вы обнаружите, что запрос по нескольким полям кажется медленным, вы можете сделать его быстрым, вручную создав составной индекс для полей в этих запросах. Затем бэкэнд будет использовать этот составной индекс во всех будущих запросах, а не полагаться на зигзагообразное соединение слиянием, что означает, что этот запрос снова масштабируется до размера результирующего набора.
Причина № 4: Вы привыкли к работе с БД в реальном времени
Хотя Cloud Firestore имеет более продвинутые возможности запросов, лучшую надежность и масштабируется лучше, чем база данных Firebase Realtime, база данных Realtime обычно имеет меньшую задержку, если вы находитесь в Северной Америке. Обычно это немного, и в чем-то вроде приложения для чата, я сомневаюсь, что вы заметите разницу. Но если у вас есть приложение, которое зависит от очень быстрых откликов базы данных (что-то вроде приложения для рисования в реальном времени или, возможно, многопользовательской игры), вы можете заметить, что база данных в реальном времени выглядит … э-э … в реальном времени.
Как это улучшить
Если ваш проект таков, что вам нужна меньшая задержка, которую обеспечивает Realtime Database (и вы ожидаете, что большинство ваших клиентов находятся в Северной Америке), и вам не нужны некоторые функции, которые предоставляет Cloud Firestore, не стесняйтесь использовать базу данных в реальном времени для этих частей вашего проекта! Прежде чем сделать это, я бы порекомендовал ознакомиться с этим более ранним сообщением в блоге или официальной документацией, чтобы убедиться, что вы понимаете полный набор компромиссов между ними.
Причина № 5: законы физики подавляют вас
Помните, что даже в самой идеальной ситуации, если ваш экземпляр Cloud Firestore размещен в Оклахоме, а ваш клиент находится в Нью-Дели, у вас будет не менее 80 миллисекунд задержки из-за всей этой «скорости света». И, реально, вы, вероятно, смотрите на что-то большее, чем 242 миллисекунды, для любого сетевого вызова. Таким образом, независимо от того, насколько быстро Cloud Firestore отвечает, вам все равно нужно время, чтобы этот ответ прошел между Cloud Firestore и вашим устройством.
Как ускориться
Во-первых, я бы рекомендовал использовать listener-ы в реальном времени вместо разовых выборок. Это происходит потому, что использование прослушивателей в реальном времени в клиентских SDK дает вам множество действительно хороших функций компенсации задержки. Например, Cloud Firestore представит вашему слушателю кэшированные данные, пока он ожидает возврата сетевого вызова, что дает вам возможность быстрее показывать результаты вашему пользователю. А записи в базу данных немедленно применяются к вашему локальному кешу, что означает, что вы увидите, что эти изменения отражаются почти мгновенно, пока ваше устройство ожидает, пока сервер подтвердит их.
Во-вторых, постарайтесь разместить ваши данные там, где собирается большинство ваших клиентов. У вас есть возможность выбрать местоположение в Cloud Firestore при первой инициализации экземпляра базы данных, поэтому подумайте, какое расположение наиболее целесообразно для вашего приложения, не только с точки зрения затрат, но и с точки зрения производительности.
В-третьих, рассмотрите возможность внедрения надежной и дешевой глобальной сети связи, основанной на квантовой запутанности, позволяющей обойти скорость света. После того, как вы это сделаете, вы, вероятно, сможете отказаться от лицензионных сборов и забыть о том, какое приложение вы изначально создавали.
Здесь большой захватывающий вывод!
Поэтому в следующий раз, когда вы столкнетесь с медленным выполнением запроса в Cloud Firestore, просмотрите этот список и подумайте, не попадаете ли вы в один из этих сценариев.
Несмотря на это, не забывайте, что лучший способ увидеть, насколько хорошо работает ваше приложение, — это измерить его производительность в реальных условиях, и Firebase Performance Monitoring — отличный способ сделать это. Подумайте о том, чтобы добавить мониторинг производительности в свое приложение и настроить одну или две пользовательских трассировки, чтобы вы могли видеть, как ваши запросы выполняются в режиме реального времени.
-
Приложения4 дня назад
Перевод по фото для iOS и Android 2025
-
Приложения6 дней назад
Решение уравнений по фотографии — приложения для математиков
-
Исследования4 недели назад
Поможет ли новая архитектура React Native отобрать лидерство у Flutter в кроссплатформенной разработке?
-
Аналитика магазинов4 недели назад
CapCut поглощает рынок видеоредакторов