преобразование нативного SQL в SQLAlchemy - PullRequest
0 голосов
/ 05 октября 2011

У меня возникла следующая проблема: я знаю SQL и не знаю, как работать с SQLAlchemy, но мне нужно изменить его на 1 место в проекте, который я унаследовал. Итак, у меня есть это:

ModelCategories = request.sa.query(
    Model.category_id
    , Category.name
    , Category.alias).distinct().join(Category).order_by(Category.alias
    , Category.name )

И он генерирует довольно медленный запрос:

SELECT DISTINCT 
  model.category_id AS model_category_id
  , category.name AS category_name
  , category.alias AS category_alias 
FROM model 
JOIN category ON category.id = model.category_id 
ORDER BY category.alias, category.name

И мне нужно изменить это следующим образом:

SELECT 
  model.category_id AS model_category_id
  , category.name AS category_name
  , category.alias AS category_alias 
FROM ( SELECT DISTINCT model_category_id ) as model 
JOIN category ON category.id = model.category_id 
ORDER BY category.alias, category.name

Но с точки зрения SQLAlchemy, как и первый запрос.

1 Ответ

2 голосов
/ 05 октября 2011

Прежде всего, проверьте план выполнения SQL.Если у вас есть index в столбце model.category_id, запрос не должен быть медленным.В противном случае доступны следующие параметры:

Опция 1: почти ваше текущее решение

# python
ModelCategories = session.query(Category).distinct().join(Model).order_by(Category.alias, Category.name)

# SQL
SELECT DISTINCT category.id AS category_id, category.name AS category_name, category.alias AS category_alias 
FROM category 
JOIN model ON category.id = model.category_id 
ORDER BY category.alias, category.name

Это похоже на ваше текущее решение, но, на мой взгляд, несколько чище.Я предполагаю, что проблема производительности может быть связана с тем, что в запросе используется вся таблица Model, и поэтому вам также необходимо использовать distinct.

Option-2: использовать любой() для отношений

# python (assumption: model mapping has relationship defined between Category and Model
mapper(Category, category_table, properties={
    'models': relationship(Model, backref="category") })

# python
ModelCategories = session.query(Category).filter(Category.models.any()).order_by(Category.alias, Category.name)

# SQL
SELECT category.id AS category_id, category.name AS category_name, category.alias AS category_alias 
FROM category 
WHERE EXISTS (SELECT 1 
    FROM model 
    WHERE category.id = model.category_id)
ORDER BY category.alias, category.name

Это должно уже повысить вашу производительность.Я предпочитаю этот вариант-3, так как он снова более чистый код

Вариант-3: использовать подзапрос

# python
q = select([Model.category_id]).distinct().alias("subq")
ModelCategories = session.query(Category).join(q, Category.id==q.c.category_id)

# SQL
SELECT category.id AS category_id, category.name AS category_name, category.alias AS category_alias 
FROM category
JOIN (SELECT DISTINCT model.category_id AS category_id FROM model) AS subq 
  ON category.id = subq.category_id
ORDER BY category.alias, category.name

Это должно дать вам именно тот SQL, который выпопросил о.Как уже упоминалось, я лично предпочитаю version-2 .

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