Как я могу сделать запрос ORM, который использует MySQL поздний поиск строк? - PullRequest
1 голос
/ 19 сентября 2019

В моем приложении django я определил модель следующим образом:

class NamedContainer(models.Model):
    name = models.CharField(max_length=50)
    capacity_ml = models.PositiveIntegerField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['name', 'capacity_ml']

Со временем эта таблица стала достаточно большой, чтобы начать вызывать некоторые проблемы с производительностью запросов, особенно при использовании предела /смещение для нарезки .Другие методы нарезки могут иметь лучшую производительность по конструкции, но пока, к сожалению, я застрял с лимитом / смещением.

Однако MySQL имеет технику, называемую «поиск в конце строки» , которая значительнопомогает с моей проблемой, и, короче говоря, необработанный запрос MySQL, использующий эту технику, может выглядеть примерно так:

SELECT t2.* FROM (
    SELECT *
    FROM `core_namedcontainer`
    WHERE `updated_at` >= '2019-01-01 05:00:00.000Z'
    ORDER BY id ASC
    LIMIT 500 OFFSET 10000
) AS t1
JOIN `core_namedcontainer` AS t2
ON t1.id = t2.id
ORDER BY `name` ASC, `capacity_ml` ASC

Мне удалось только манипулировать запросом ORM, чтобы создать запрос типа

SELECT *
FROM `core_namedcontainer`
WHERE (
  `core_namedcontainer`.`id` IN (
      SELECT U0.`id`
      FROM `core_namedcontainer` U0
      WHERE (
        U0.`updated_at` >= 2019-01-01 05:00:00
      )
      ORDER BY U0.`name` ASC, U0.`capacity_ml` ASC
      LIMIT 500 OFFSET 10000
    )
)
ORDER BY `core_namedcontainer`.`name` ASC, `core_namedcontainer`.`capacity_mL` ASC

, который просто использует подзапрос вместо соединения с самим собой, и при оценке запроса MySQL жалуется с помощью

NotSupportedError: (1235, "This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'")

Приложение django использует MySQL 5.6 и по ряду причинпотребуется некоторое время, прежде чем он сможет обновиться до чего-то более нового.

Я знаю, что могу просто выполнить необработанный SQL-запрос так, как мне нужно, но я надеюсь, что есть способпереведите эту технику в синтаксис Django ORM, чтобы я мог использовать эту технику в своей модели в качестве базового набора запросов:

class NamedContainerManager(models.Manager):
    def get_queryset(self):
        queryset = super().get_queryset()
        # do some ORM magic here to implement mysql late row lookup in all queries
        return queryset

class NamedContainer(models.Model):
    ...
    objects = NamedContainerManager()

Вся помощь очень ценится!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...