Почему мой API получает данные из базы данных быстрее, чем из Redis?

Я работаю с Django и GraphQL, чтобы создать бэкэнд для приложения электронной коммерции. Изначально API для получения товаров был медленным, поэтому я решил реализовать стек Redis, чтобы ускорить его. Однако я обнаружил, что получение данных из Redis происходит гораздо медленнее, чем из базы данных. Ниже приведены детали моей реализации:

Запрос к базе данных:

def resolve_products(self, info, **kwargs):
    (filter_objects, method_filter, seller_lst, name, ar_name) = (
        product_obj.call_filter_product()
    )
    kwargs["seller_list"] = eller_lst
    query = (
        Products.objects.filter(filter_objects, method_filter, active=True)
        .filter(variants__seller__id__in=list(seller_lst))
        .distinct()
    )
    query = query.filter(
        Exists(
            Variant.objects.filter(
                product_id=OuterRef("id"),
                seller_id__in=seller_lst,
                stock_available=True,
            )
        )
    )

    start_index = int(offset)
    end_index = start_index + int(kwargs.get("first"))
    query_set = query[start_index:end_index]
    final_qs = query_set.annotate(
        stock_available=Exists(
            Variant.objects.filter(
                product_id=OuterRef("id"),
                seller_id__in=seller_lst,
                stock_available=True,
            )
        )
    )

    # Determine hasNextPage
    has_next_page = end_index < len(query)
    connection = ProductsConnection(
        edges=[ProductsConnection.Edge(node=product) for product in final_qs],
        total_count=query.count(),
        details={
            "header_en": name,
            "header_ar": ar_name,
            "method": kwargs.get("method"),
        },
    )
    connection.page_info = PageInfo(
        start_cursor=start_index,
        end_cursor=(
            int(kwargs.get("first")) + 1
            if int(offset) == 0
            else int(offset) + int(kwargs.get("first"))
        ),
        has_next_page=has_next_page,
        has_previous_page=start_index > 0,
    )
    return connection

Реализация Redis:

seller_lst = obj.get_seller_lst()
redis_obj = RedisUtility()

data = redis_obj.get_products(seller_lst, **kwargs)
if data:
    product_ids = [int(product['id']) for product in data['products']]

    products = Products.objects.filter(id__in=product_ids)
    connection = ProductsConnection(
        edges=[ProductsConnection.Edge(node=product) for product in products],
        total_count=data['total_count'],
        details={
            "header_en": "name",
            "header_ar": "ar_name",
            "method": kwargs.get("method"),
        },
    )
    connection.page_info = relay.PageInfo(
        start_cursor=str(data['offset']),
        end_cursor=str(
            int(kwargs.get("first")) + 1
            if int(data['offset']) == 0
            else int(data['offset']) + int(kwargs.get("first"))
        ),
        has_next_page=data['end_index'] < data['total_count'],
        has_previous_page=data['offset'] > 0,
    )

    return connection

Утилита Redis:

class RedisUtility:
    def __init__(
        self,
        host=settings.REDIS_STACK_HOST,
        port=settings.REDIS_STACK_PORT,
        username=settings.REDIS_STACK_USERNAME,
        password=settings.REDIS_STACK_PASSWORD,
        decode_responses=settings.REDIS_STACK_DECODE_RESPONSES,
    ):
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.decode_responses = decode_responses
        self.connection = None

    def connect(self):
        if not self.connection:
            self.connection = get_redis_connection(
                host=self.host,
                port=self.port,
                username=self.username,
                password=self.password,
                decode_responses=self.decode_responses,
            )
        return self.connection

    def get_products(self, seller_lst, **kwargs):
        r = self.connect()

        offset = kwargs.get("after") if kwargs.get("after") else 0
        limit = int(kwargs.get("first", 10))
        category_ids = self.get_category_ids(kwargs.get('slug'), kwargs.get('level'))
        
        category_query = f"@category:{{{' | '.join(map(str, category_ids))}}}"
        seller_query = f"@stock_available_seller:{{{' | '.join(map(str, seller_lst))}}}"
        final_query = f"({category_query}) (@stock_available_seller:({seller_query}))"
        count_query = Query(final_query)
        total_count = r.ft(':product:index').search(count_query).total

        q = Query(final_query).paging(offset, limit)
        result = r.ft(':product:index').search(q)
        
        products = [json.loads(doc.json) for doc in result.docs]
        
        return {
            'total_count': total_count,
            'offset': offset,
            'end_index': offset + limit,
            'products': products
        }

Проблема: Несмотря на внедрение Redis, API работает медленнее, чем при получении данных напрямую из базы данных. Я ожидал, что Redis ускорит этот процесс, но все происходит наоборот.

Вопросы:

  1. Какие причины могут быть причиной низкой производительности при использовании Redis?
  2. Как можно оптимизировать реализацию Redis для улучшения времени отклика?
  3. Существуют ли какие-либо лучшие практики использования Redis с Django/GraphQL для обеспечения лучшей производительности? Любые соображения или предложения будут очень признательны. Спасибо!
Вернуться на верх