Django QuerySet vs desempenho de consulta Raw

Eu notei uma enorme diferença de tempo entre o uso do django connection.cursor vs o uso da interface do modelo, mesmo com pequenos conjuntos de consultas. Eu tornei a interface do modelo o mais eficiente possível, com values_list para que nenhum objeto seja construído e tal. Abaixo estão as duas funções testadas, não se importe com os nomes em espanhol.

def t3():
    q = "select id, numerosDisponibles FROM samibackend_eventoagendado LIMIT 1000"
    with connection.cursor() as c:
        c.execute(q)
        return list(c)

def t4():
    return list(EventoAgendado.objects.all().values_list('id','numerosDisponibles')[:1000])

Em seguida, usando uma função para cronometrar (criada por time.clock ())

r1 = timeme(t3); r2 = timeme(t4)

Os resultados são os seguintes: 0,00180384529631 e 0,00493390727024 para t3 e t4

E apenas para garantir que as consultas sejam e faça o mesmo para executar:

connection.queries[-2::]

Rendimentos:

[
    {u'sql': u'select id, numerosDisponibles FROM samibackend_eventoagendado LIMIT 1000',  u'time': u'0.002'},
    {u'sql': u'SELECT `samiBackend_eventoagendado`.`id`, `samiBackend_eventoagendado`.`numerosDisponibles` FROM `samiBackend_eventoagendado` LIMIT 1000', u'time': u'0.002'}
]

Como você pode ver, duas consultas exatas, retornando duas listas exatas (executando r1 == r2 retorna True), levam tempos totalmente diferentes (a diferença aumenta com um conjunto maior de consultas), eu sei que o python é lento, mas o django está fazendo muito trabalhar nos bastidores para tornar a consulta mais lenta? Além disso, apenas para ter certeza, tentei criar o objeto queryset primeiro (fora do cronômetro), mas os resultados são os mesmos, por isso tenho 100% de certeza de que o tempo extra vem da busca e construção da estrutura de resultados. Eu também tentei usar a função iterator () no final da consulta, mas isso também não ajuda. Eu sei que a diferença é mínima, ambos são extremamente rápidos, mas isso está sendo carregado com o apache ab, e essa diferença mínima, ao ter 1k solicitações simultâneas, torna o dia e a luz.

A propósito, estou usando o django 1.7.10 com o mysqlclient como o conector db.

EDIT: Para fins de comparação, no mesmo teste com um conjunto de consultas de resultados de 11k, a diferença fica ainda maior (3x mais lenta, em comparação com a primeira em que é cerca de 2,6x mais lenta)

r1 = timeme(t3); r2 = timeme(t4)
0.0149241530889
0.0437563529558

EDIT2: Outro teste engraçado, se eu realmente converter o objeto queryset em sua consulta de string real (com str (queryset.query)) e usá-lo dentro de uma consulta bruta, obtive o mesmo bom desempenho da consulta bruta, pelo Execução de que o uso da string queryset.query às vezes me fornece uma consulta SQL inválida real (ou seja, se o conjunto de consultas tiver um filtro em um valor de data, o valor da data não será escapado com '' na consulta de string, gerando um erro sql ao executar com uma consulta bruta, esse é outro mistério)

- EDIT3: Ao percorrer o código, parece que a diferença é feita pela maneira como os dados do resultado são recuperados. Para um conjunto de consultas brutas, ele simplesmente chamaiter(self.cursor) que acredito que ao usar um conector implementado em C seja executado em código C (como o iter também é incorporado), enquanto o ValuesListQuerySet é na verdade um nível de python para loop com uma instrução de tupla (linha) de rendimento, que será bastante lenta. Eu acho que não há nada a ser feito neste assunto para ter o mesmo desempenho que o conjunto de consultas brutas: '(. Se alguém estiver interessado, o loop lento é este:

for row in self.query.get_compiler(self.db).results_iter():
    yield tuple(row)

- EDIÇÃO 4: Eu vim com um código muito hacky para converter uma consulta da lista de valores configurada em dados utilizáveis a serem enviados para uma consulta bruta, com o mesmo desempenho que a execução de uma consulta bruta, acho que isso é muito ruim e só funcionará com o mysql, mas , a velocidade é muito boa, permitindo que eu mantenha a filtragem da API do modelo e tal. O que você acha? Aqui está o código.

def querysetAsRaw(qs):
    q = qs.query.get_compiler(qs.db).as_sql()
    with connection.cursor() as c:
        c.execute(q[0], q[1])
        return c

questionAnswers(1)

yourAnswerToTheQuestion