A linguagem SQL possui algumas funções úteis para fazer análises estatísticas. Normalmente você encontrará funções como sum, average, max e min que retornam a soma, média, valor máximo e mínimo de uma determinada coluna, respectivamente. Essas funções são chamadas de "agregações", pois elas retornam um único dado com base em uma série de dados, ou seja, elas agregam esses dados.

É difícil falar de SQL em geral pois cada distribuidor faz o seu próprio "jeitinho" de SQL, formalmente conhecidos como dialetos. O SQL usado pelo Google BigQuery, por exemplo, possui um ecossistema riquíssimo de funções estatísticas prontas. O ponto desse post, porém, é mais amplo:

É mais eficiente em termos de tempo de execução utilizar dessas funções prontas do SQL ou fazer as análises em seja lá qual linguagem de programação a gente tá usando?

Um Exemplo em Python

O código abaixo foi recortado para exibir apenas as partes mais importantes.

Considere duas funções diferentes para somar o total de valores de uma coluna chamada "Milliseconds". A primeira, faz uma query para listar todos os resultados da tabela, passa por todos os resultados um a um e soma o valor da coluna numa variável:

def sum_manual():
    query = select(track)
    result = engine.execute(query)

    sum_ = 0
    for row in result:
        sum_ += row.Milliseconds
    return sum_
Somando a coluna milliseconds manualmente

A segunda função, por outro lado, envia para o servidor SQL uma query pedindo pelo resultado de sum. Ou seja, quem vai fazer o trabalho é o servidor SQL e não nosso código:

def sum_sql():
    query = select(func.sum(track.columns["Milliseconds"]))
    result = engine.execute(query)
    return result.scalar()

Com a função mágica %timeit do Jupyter e do ipython, podemos comparar os resultados:

%timeit sum_manual()
2.07 s ± 13.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit sum_sql()
39.1 ms ± 418 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
Comparando as performances

Ou seja, somar manualmente levou, em média, 2.07s. Somar através do SQL, 39.1ms. A função que utiliza de SQL foi quase 53 vezes mais rápida do que a manual.

Em geral, esse é o comportamento que veremos - utilizar do servidor de SQL para fazer essas operações é mais rápido. A análise aqui foi bastante limitada - o servidor SQL era simplesmente um SQLite que estava rodando na minha máquina local - e ainda assim conseguimos ver diferenças.

Você talvez já tenha ouvido falar sobre coisas como "análise de complexidade de algoritmos", "notação grande-O (big-O)", "análise assintótica" e outras coisas do tipo. É possível utilizar de ferramentas assim para fazer uma análise mais detalhada dessas duas funções. Mais tarde, nessa mesma semana, publico uma análise do tipo. Se inscreva na newsletter do blog para ficar sabendo das novidades :D