使用Django Rest框架的Mysql多连接性能

使用Django Rest框架的Mysql多连接性能,mysql,django,database,django-rest-framework,relational-database,Mysql,Django,Database,Django Rest Framework,Relational Database,我一直在努力解决一个问题,我相信每个人在某个时候都会遇到这个问题。我现在有一个150k产品的小数据库。(在我写这篇文章的过程中不断增加。) 我在api中使用DRF,并且一直在为我拥有的许多产品的类别性能而挣扎 也就是说,我有一个名为连衣裙的类别,它有34633产品。 我的数据库是如何设计的,我在它下面有几个关系 产品有类别、属性、颜色、尺寸、相关产品M2M 查询 计数查询809.83ms 结果查询2139.52ms 正如你所看到的,时间对于一个查询来说太多了,但当我应用过滤器时,这里有一个棘手的

我一直在努力解决一个问题,我相信每个人在某个时候都会遇到这个问题。我现在有一个150k产品的小数据库。(在我写这篇文章的过程中不断增加。)

我在api中使用DRF,并且一直在为我拥有的许多产品的类别性能而挣扎

也就是说,我有一个名为连衣裙的类别,它有
34633
产品。 我的数据库是如何设计的,我在它下面有几个关系

产品有类别、属性、颜色、尺寸、相关产品
M2M

查询

计数查询
809.83
ms

结果查询
2139.52
ms

正如你所看到的,时间对于一个查询来说太多了,但当我应用过滤器时,这里有一个棘手的部分,即我选择颜色过滤器,并且大小时间开始减少

应用过滤器的查询

计数查询
264.63
ms

结果查询
351.43
ms

我已经尝试了很多方法来解决这个问题,但无法解决这个问题。我需要提高页面加载的速度,但由于查询耗时较长,这对用户来说并不太好。 我已经使用了渴望加载,所以它将不再有助于提高,除非你有任何补充

代码

序列化程序

看法

只是一个建议 查看您的查询代码 确保你有合适的综合指数

table catalog_products  index  on (deleted, in_stock, id )
table catalog_products_category index  on  ( categories_id, products_id, id  )
并避免代码周围出现无用的()

SELECT COUNT(*) 
FROM (
  SELECT DISTINCT `catalog_products`.`id` AS Col1 
  FROM `catalog_products` 
  INNER JOIN `catalog_products_category` 
    ON `catalog_products`.`id` = `catalog_products_category`.`products_id` 
  WHERE `catalog_products`.`deleted` = 0 
  AND `catalog_products`.`in_stock` = 1 
  AND `catalog_products_category`.`categories_id` = 183
  ) subquery


SELECT DISTINCT `catalog_products`.`id`
  , `catalog_products`.`sku`
  , `catalog_products`.`title`
  , `catalog_products`.`old_price`
  , `catalog_products`.`price`
  , `catalog_products`.`sale`
  , `catalog_products`.`original_categories`
  , `catalog_products`.`original_conv_color`
  , `catalog_products`.`original_sizes` 
FROM `catalog_products` 
INNER JOIN `catalog_products_category` 
  ON `catalog_products`.`id` = `catalog_products_category`.`products_id`
WHERE `catalog_products`.`deleted` = 0 
AND `catalog_products`.`in_stock` = 1 
AND `catalog_products_category`.`categories_id` = 183 
ORDER BY `catalog_products`.`title` ASC LIMIT 48

最后一个建议记住,排序方式对排序有相当大的影响,但对结果引入限制意味着必须选择所有行,仅根据限制处指示的数字进行排序和最终提取。

老实说,您的查询的优化似乎是完全可能的。我相信这是使用正确索引的问题

我不知道每个表上的列选择性的所有细节(这是必要的),因此我假设,例如,
categories\u id=183
实际上会过滤掉大部分行;我可能错了。我将对所有相关的表采用类似的选择性(
catalog\u products\u category
catalog\u products\u color
,以及
catalog\u sizethrough

如果是这样,我建议使用以下索引来加快搜索速度:

create index ix1 on catalog_products_category (categories_id, products_id);
create index ix2 on catalog_products_color (color_id, products_id);
create index ix3 on catalog_sizethrough (size_id, stock, products_id);
create index ix4 on catalog_products (deleted, in_stock, id);

试试看。如果您的查询仍然很慢,请发布最慢的查询的执行计划以进行解释。

感谢您的回复,我已经为所需列编制了索引,在catalog\u products.id上我有“Primary”,在catalog\u products\u category(id,products\u id,categories id)上我有(Primary,unique,Index)。请让我知道这是否是好的,或者我应该有索引类型“索引”对所有的。括号也出现在我的脑海中,但似乎它们没有造成任何伤害。到目前为止,使用括号查询速度更快。我不知道为什么,因为我也认为应该是另一种方式。显示您的表架构。。你在评论中提到的索引对我来说似乎不是最佳的,我再次感谢你的回复。当你提到索引时,我仔细检查了我的查询和数据库结构,所有索引都在正确的位置,但是如果你注意到我在查询中按标题排序的话。这花了我们所有的时间。感谢您的快速回复。如果您能按照我解释的方式更新答案,我将接受您的答案,否则我必须为看到此问题的其他人写一封。@ShanKhaliq。。回答更新,并提供一些关于订购和限制成本的建议
SELECT DISTINCT `catalog_products`.`id`, `catalog_products`.`sku`,
  `catalog_products`.`title`, `catalog_products`.`old_price`,
  `catalog_products`.`price`, `catalog_products`.`sale`,
  `catalog_products`.`original_categories`,
  `catalog_products`.`original_conv_color`,
  `catalog_products`.`original_sizes` 
FROM `catalog_products` 
INNER JOIN `catalog_products_color` ON (`catalog_products`.`id` =
                         `catalog_products_color`.`products_id`) 
INNER JOIN `catalog_products_category` ON (`catalog_products`.`id` =
                         `catalog_products_category`.`products_id`) 
INNER JOIN `catalog_sizethrough` ON (`catalog_products`.`id` =
                          `catalog_sizethrough`.`product_id`) 
WHERE (`catalog_products`.`deleted` = 0 
  AND `catalog_products`.`in_stock` = 1 
  AND `catalog_products_color`.`color_id` = 1 
  AND `catalog_products_category`.`categories_id` = 183 
  AND `catalog_sizethrough`.`size_id` IN (262) 
  AND `catalog_sizethrough`.`stock` = 1) 
ORDER BY `catalog_products`.`title` ASC 
LIMIT 48
class ProductsListSerializer(serializers.ModelSerializer):

images = ImagesSerializer(many=True, source='get_first_two_images')
related_color = serializers.SerializerMethodField()

def get_related_color(self, obj):
    return obj.related_color.count()

class Meta:

    fields = (
        'id',
        'sku',
        "title",
        "old_price",
        "price",
        "sale",
        "images",
        "original_categories",
        "related_color",
        "original_conv_color",
        "original_sizes",
    )
    model = Products

@staticmethod
def setup_eager_loading(queryset):
    queryset = queryset.only('id', 'sku', 'title', 'old_price', 'price', 'sale', 'original_categories', 'original_conv_color', 'original_sizes').prefetch_related('images', 'related_color')

    return queryset
class ProductsViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Products.objects.all()
permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
filter_backends = (filters.SearchFilter, DjangoFilterBackend, filters.OrderingFilter, CustomFilter, SizeFilter)
filter_fields = ('slug', 'code', 'sku', 'color', 'attributes', 'category', 'original_color')
min_max_fields = ('price', 'sale')
search_fields = ('title', 'original_color', 'original_categories', 'original_conv_color', 'original_sizes')
ordering_fields = ('sale', 'price', 'created_at')
pagination_class = StandardResultsSetPagination

def get_queryset(self):
    if self.action == 'list':
        queryset = self.get_serializer_class().setup_eager_loading(self.queryset.filter(deleted=0,in_stock=1))
        return queryset
    return self.queryset

def get_serializer_class(self):
    if self.action == 'list':
        return ProductsListSerializer
    if self.action == 'retrieve':
        return ProductsSerializer
    return ProductsSerializer
table catalog_products  index  on (deleted, in_stock, id )
table catalog_products_category index  on  ( categories_id, products_id, id  )
SELECT COUNT(*) 
FROM (
  SELECT DISTINCT `catalog_products`.`id` AS Col1 
  FROM `catalog_products` 
  INNER JOIN `catalog_products_category` 
    ON `catalog_products`.`id` = `catalog_products_category`.`products_id` 
  WHERE `catalog_products`.`deleted` = 0 
  AND `catalog_products`.`in_stock` = 1 
  AND `catalog_products_category`.`categories_id` = 183
  ) subquery


SELECT DISTINCT `catalog_products`.`id`
  , `catalog_products`.`sku`
  , `catalog_products`.`title`
  , `catalog_products`.`old_price`
  , `catalog_products`.`price`
  , `catalog_products`.`sale`
  , `catalog_products`.`original_categories`
  , `catalog_products`.`original_conv_color`
  , `catalog_products`.`original_sizes` 
FROM `catalog_products` 
INNER JOIN `catalog_products_category` 
  ON `catalog_products`.`id` = `catalog_products_category`.`products_id`
WHERE `catalog_products`.`deleted` = 0 
AND `catalog_products`.`in_stock` = 1 
AND `catalog_products_category`.`categories_id` = 183 
ORDER BY `catalog_products`.`title` ASC LIMIT 48
create index ix1 on catalog_products_category (categories_id, products_id);
create index ix2 on catalog_products_color (color_id, products_id);
create index ix3 on catalog_sizethrough (size_id, stock, products_id);
create index ix4 on catalog_products (deleted, in_stock, id);