suggest-indexes proposes composite indexes that include the primary key or a unique field
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 82/100
Línea de trabajo
Empieza en cli/orm_lens/query_analyzer.py en suggest_indexes(), donde están disponibles pk_name y target_model, y luego lee el bucle de compuestos al inicio de _propose_indexes(). Construye un conjunto de columnas únicas individuales (la PK, pk, los campos con primary_key=True o unique=True, y los OneToOneFields) y omite cualquier compuesto que contenga una de ellas, dejando intacta la lógica de campos individuales. Está listo cuando el reproductor de Story solo produce ['status'] y ['title'], pk= se comporta como id=, y cli/tests/test_query_analyzer.py junto con pytest, ruff y mypy pasan.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Source: weblate — trans.Unit: models.Index(fields=['id', 'translation'])
What happens
filter(id=pk, title=title) seen twice gives models.Index(fields=['id', 'title']). The primary key is unique: an equality lookup on it returns at most one row, so the PK index already answers the query and a composite led by id only costs writes and disk. The same is true for any unique=True field.
_propose_indexes() uses already_indexed for single-field proposals only. The composite loop checks the M2M/reverse filter from #252/#263 and existing Meta groups, nothing else. pk= is folded into id before that, so both spellings hit it.
On weblate trans.Unit gets models.Index(fields=['id', 'translation']).
Repro
board/models.py
from django.db import models
class Story(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
status = models.CharField(max_length=20)
board/stats.py
from .models import Story
def by_id_and_title(pk, title):
return Story.objects.filter(id=pk, title=title).first()
def by_id_and_title_again(pk, title):
return Story.objects.get(id=pk, title=title)
def by_pk_and_status(pk, status):
return Story.objects.filter(pk=pk, status=status).exists()
def by_pk_and_status_again(pk, status):
return Story.objects.filter(pk=pk, status=status).first()
def by_slug_and_status(slug, status):
return Story.objects.filter(slug=slug, status=status).first()
def by_slug_and_status_again(slug, status):
return Story.objects.filter(slug=slug, status=status).exists()
$ orm-lens suggest-indexes board.Story
target: board.Story
proposed Meta.indexes (5):
models.Index(fields=['id', 'status']), # 2 composite filter sites
models.Index(fields=['id', 'title']), # 2 composite filter sites
models.Index(fields=['slug', 'status']), # 2 composite filter sites
models.Index(fields=['status']), # 4 filter sites
models.Index(fields=['title']), # 2 filter sites
Expected: only ['status'] and ['title']. The usage table can keep listing id + title etc.
Where
cli/orm_lens/query_analyzer.py
- line 497,
_propose_indexes(); the composite loop is right at the top of the function body; - line 309,
_indexed_single_fields(): buildsalready_indexed, but it also containsdb_index=Truefields and FKs, which are not unique, so it can't be reused as is; - line 598,
suggest_indexes():pk_name(line 675) andtarget_modelare both there.
Suggested fix
In suggest_indexes(), build the set of unique single columns: pk_name, "pk", every field with primary_key=True or unique=True (the _PK_TRUE_RE / _UNIQUE_TRUE_RE regexes are already in the module), and OneToOneFields (unique by definition). Pass it to _propose_indexes() as a new keyword argument and skip a composite combo that contains any of these names.
Don't touch the single-field and order_by logic.
How to test
cli/tests/test_query_analyzer.py: the repro gives exactly['status']and['title'].filter(pk=..., ...)is dropped the same asfilter(id=..., ...).- A model with
code = models.CharField(primary_key=True)drops a['code', 'title']composite. - A composite of two non-unique fields (
filter(title=..., status=...)) is still proposed. cd cli && python -m pytest -q,ruffandmypypass.
Difficulty: good first issue, one set and one if.
- Lenguaje dominante
- Python
- Estrellas
- 84
- Forks
- 13
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
- Incluye un Dockerfile o un archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de FROWNINGdev/django-orm-lens
-
`migration-risk` text output prints `app.None` for graph-level findingsPosiblemente ocupada @phoenixbycaselka la tomó hoy. Abiertobug good first issue python
Dificultad 1/5 1-3 horas Aptitud para principiantes 88/100
FROWNINGdev/django-orm-lens#268 ·
-
Finish the Chinese rule reference — DOL001–DOL007Quizá libre de nuevo @harbinresearcher la tomó hace 64 días y no hay ningún pull request abierto. Abiertodocumentation good first issue help wanted
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
FROWNINGdev/django-orm-lens#81 · 2 comentarios ·
-
Fields inherited from Django's `AbstractBaseUser` / `PermissionsMixin` / `AbstractUser` are missingAbiertobug good first issue python
Dificultad 3/5 1-2 días Aptitud para principiantes 62/100
FROWNINGdev/django-orm-lens#267 ·
-
bug good first issue python
Dificultad 3/5 Medio día Aptitud para principiantes 78/100
FROWNINGdev/django-orm-lens#266 ·
-
enhancement help wanted python
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
FROWNINGdev/django-orm-lens#254 ·
Todos los issues de FROWNINGdev/django-orm-lens
Issues similares
-
generate_observation_scenario_from_cpgs exposure time conversion when auto-gain set to 'yes'Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
roman-corgi/corgisim#327 ·
Los mantenedores suelen responder en 2 días
-
[Bug]: opencode_go chat route drops reasoning_effort (even 'none'), while the same endpoint honors it via custom_llm_provider=openaiPosiblemente ocupada @arvindkumar-ship-it la tomó hoy. Abiertollm translation
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
BerriAI/litellm#51871 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
PolicyEngine backdates South Carolina’s EITC into 2015–2017Posiblemente ocupada @MaxGhenis la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
PolicyEngine/policyengine-us#10944 ·
Los mantenedores suelen responder en 2 días
-
fix(frontend): resolve SSE parser crash on unhandled Ref methods and undefined actions identifierAbiertobug
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
kodokbakar/MiroFish-Local#94 ·
Los mantenedores suelen responder en 1 día