Algumas coisas saltam à tona.
Em primeiro lugar, se este código está sendo chamado 2000 vezes e leva 250ms extras para ser executado, isso é ~0,125ms por chamada para converter o Arel para SQL, o que não é irreal.
Em segundo lugar, não tenho certeza dos componentes internos do Range em Ruby, mas
lower..upper
pode estar fazendo cálculos como o tamanho do intervalo e outras coisas, o que será um grande impacto no desempenho. Você vê o mesmo desempenho atingido com o seguinte?
sum = Table.
where(:id => id).
where(:created_at => "BETWEEN ? and ?", lower, upper).
sum(:my_column)