ActiveRecord vacío? vs contar

Durante una discusión con un compañero de trabajo sobre la optimización de consultas sobre rieles, ¿necesito demostrar mi teoría de que el recuento es más rápido que el vacío? porque en el primer método, el registro activo se realiza directamente sobre sql y en el segundo está verificando la longitud de la matriz dada por el resultado.

Mi entorno

ruby 1.9.3-p448
rails
3.2.6

Entonces, para demostrarlo, hice el siguiente punto de referencia

Código

Benchmark.bm do |bm|

bm
.report("count") do
10.times{ User.where('id>0').count<0 }
end

bm
.report("empty?") do
10.times{ User.where('id>0').empty? }
end

end

aquí la esencia

Consola

Y mi sorpresa fue que ambas consultas usan COUNT (*)

contar

[DEBUG]    (0.6ms)  SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id > 0)
[DEBUG] (0.6ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id > 0)
[DEBUG] (0.4ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id > 0)
[DEBUG] (0.5ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id > 0)
[DEBUG] (0.5ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id > 0)
[DEBUG] (0.4ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id > 0)
[DEBUG] (0.4ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id > 0)
[DEBUG] (0.4ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id > 0)
[DEBUG] (0.4ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id > 0)
[DEBUG] (0.4ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id > 0)

¿vacío?

[DEBUG]    (0.4ms)  SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id>0)
[DEBUG] (0.5ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id>0)
[DEBUG] (0.4ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id>0)
[DEBUG] (0.3ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id>0)
[DEBUG] (0.4ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id>0)
[DEBUG] (0.3ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id>0)
[DEBUG] (0.4ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id>0)
[DEBUG] (0.3ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id>0)
[DEBUG] (0.3ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id>0)
[DEBUG] (0.4ms) SELECT COUNT(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND (id>0)

Resultado de referencia

          user     system      total      real
count
0.020000 0.000000 0.020000 ( 0.023109)
empty
? 0.020000 0.000000 0.020000 ( 0.018685)

Conclusión

¿Vacío? El método es un poco más rápido que contar, así que no temas usarlo, especialmente si lo llamas varias veces. Mi preocupación y espero que alguien pueda responder por qué es más rápido y por qué está llamando a COUNT (*) porque me parece que ActiveRecord está haciendo toda la magia.

Actualización 29/07/2013

Para confirmar mis dudas, ejecuto las mismas pruebas en la base de datos del escenario y con una muestra grande 1000 veces. ¿Y además de las leves diferencias vacías? sigue superando la cuenta en tiempo real.

          user     system      total      real
count
2.370000 0.100000 2.470000 ( 24.989100)
empty
? 2.470000 0.090000 2.560000 ( 24.867949)