From f215ae91087891ae1af1749e331037ec6774089d Mon Sep 17 00:00:00 2001 From: nick Date: Tue, 29 Aug 2017 22:19:44 +0100 Subject: [PATCH] Fixed performance regression caused by treating all numbers as numeric types in prepared statements --- .../PostgreSQLColumnEncoderRegistry.scala | 20 ++++++------- .../async/db/postgresql/NumericSpec.scala | 1 - .../db/postgresql/PreparedStatementSpec.scala | 29 +++++++++++++++++++ 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/postgresql-async/src/main/scala/com/github/mauricio/async/db/postgresql/column/PostgreSQLColumnEncoderRegistry.scala b/postgresql-async/src/main/scala/com/github/mauricio/async/db/postgresql/column/PostgreSQLColumnEncoderRegistry.scala index c9f95f43..2a3cd310 100644 --- a/postgresql-async/src/main/scala/com/github/mauricio/async/db/postgresql/column/PostgreSQLColumnEncoderRegistry.scala +++ b/postgresql-async/src/main/scala/com/github/mauricio/async/db/postgresql/column/PostgreSQLColumnEncoderRegistry.scala @@ -31,23 +31,23 @@ object PostgreSQLColumnEncoderRegistry { class PostgreSQLColumnEncoderRegistry extends ColumnEncoderRegistry { private val classesSequence_ : List[(Class[_], (ColumnEncoder, Int))] = List( - classOf[Int] -> (IntegerEncoderDecoder -> ColumnTypes.Numeric), - classOf[java.lang.Integer] -> (IntegerEncoderDecoder -> ColumnTypes.Numeric), + classOf[Int] -> (IntegerEncoderDecoder -> ColumnTypes.Integer), + classOf[java.lang.Integer] -> (IntegerEncoderDecoder -> ColumnTypes.Integer), - classOf[java.lang.Short] -> (ShortEncoderDecoder -> ColumnTypes.Numeric), - classOf[Short] -> (ShortEncoderDecoder -> ColumnTypes.Numeric), + classOf[java.lang.Short] -> (ShortEncoderDecoder -> ColumnTypes.Smallint), + classOf[Short] -> (ShortEncoderDecoder -> ColumnTypes.Smallint), - classOf[Long] -> (LongEncoderDecoder -> ColumnTypes.Numeric), - classOf[java.lang.Long] -> (LongEncoderDecoder -> ColumnTypes.Numeric), + classOf[Long] -> (LongEncoderDecoder -> ColumnTypes.Bigserial), + classOf[java.lang.Long] -> (LongEncoderDecoder -> ColumnTypes.Bigserial), classOf[String] -> (StringEncoderDecoder -> ColumnTypes.Varchar), classOf[java.lang.String] -> (StringEncoderDecoder -> ColumnTypes.Varchar), - classOf[Float] -> (FloatEncoderDecoder -> ColumnTypes.Numeric), - classOf[java.lang.Float] -> (FloatEncoderDecoder -> ColumnTypes.Numeric), + classOf[Float] -> (FloatEncoderDecoder -> ColumnTypes.Real), + classOf[java.lang.Float] -> (FloatEncoderDecoder -> ColumnTypes.Real), - classOf[Double] -> (DoubleEncoderDecoder -> ColumnTypes.Numeric), - classOf[java.lang.Double] -> (DoubleEncoderDecoder -> ColumnTypes.Numeric), + classOf[Double] -> (DoubleEncoderDecoder -> ColumnTypes.Double), + classOf[java.lang.Double] -> (DoubleEncoderDecoder -> ColumnTypes.Double), classOf[BigDecimal] -> (BigDecimalEncoderDecoder -> ColumnTypes.Numeric), classOf[java.math.BigDecimal] -> (BigDecimalEncoderDecoder -> ColumnTypes.Numeric), diff --git a/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/NumericSpec.scala b/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/NumericSpec.scala index ad38a64e..285f59cd 100644 --- a/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/NumericSpec.scala +++ b/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/NumericSpec.scala @@ -30,7 +30,6 @@ class NumericSpec extends Specification with DatabaseTestHelper { val id = executePreparedStatement(handler, "INSERT INTO numeric_test DEFAULT VALUES RETURNING id").rows.get(0)("id") executePreparedStatement(handler, "UPDATE numeric_test SET numcol = ? WHERE id = ?", Array[Any](1234, id)) - executePreparedStatement(handler, "UPDATE numeric_test SET numcol = ? WHERE id = ?", Array[Any](123.123, id)) id === 1 } diff --git a/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/PreparedStatementSpec.scala b/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/PreparedStatementSpec.scala index 660c1411..0629f462 100644 --- a/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/PreparedStatementSpec.scala +++ b/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/PreparedStatementSpec.scala @@ -21,8 +21,13 @@ import org.joda.time.LocalDate import com.github.mauricio.async.db.util.Log import com.github.mauricio.async.db.exceptions.InsufficientParametersException import java.util.UUID + import com.github.mauricio.async.db.postgresql.exceptions.GenericDatabaseException +import scala.concurrent.Await +import scala.concurrent.duration.{Duration, SECONDS} +import scala.util.Random + class PreparedStatementSpec extends Specification with DatabaseTestHelper { val log = Log.get[PreparedStatementSpec] @@ -371,6 +376,30 @@ class PreparedStatementSpec extends Specification with DatabaseTestHelper { } } + "not take twice the time as a non prepared statement" in { + withHandler { + handler => + executeDdl(handler, "create temp table performance_test (id integer PRIMARY KEY, int1 integer)") + (1 to 2000).foreach(i => + executeQuery(handler, s"insert into performance_test (id, int1) values ($i, ${Random.nextInt(20000)})")) + + val preparedStatementStartTime = System.nanoTime() + (1 to 2000).foreach { i => + val id = Random.nextInt(2000) + Await.result(handler.sendPreparedStatement("update performance_test set int1 = int1 where id = ?", Array(id)), Duration(5, SECONDS)) + } + val preparedStatementTime = System.nanoTime() - preparedStatementStartTime + + val plainQueryStartTime = System.nanoTime() + (1 to 2000).foreach { i => + val id = Random.nextInt(2000) + Await.result(handler.sendQuery(s"update performance_test set int1 = int1 where id = $id"), Duration(5, SECONDS)) + } + val plainQueryTime = System.nanoTime() - plainQueryStartTime + + preparedStatementTime must beLessThan(plainQueryTime * 2) + } + } } }