question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Use of Double and Decimal .Net Type via NpgsqlCommand Parameters causes massive query performance degradation

See original GitHub issue

Steps to reproduce

image

The issue

The same parameterized sql query runs orders of magnitude slower on millions of rows (see below for timing) if Double and Decimal .Net types are used as NpgsqlCommand Parameters as opposed to .Net Short and Int32 types.

The sql query look something like:

select * from product 
WHERE (product.type_id = @type_id) 
ORDER BY product.created_date DESC NULLS LAST
LIMIT @limit OFFSET @offset

The type_id in PostgreSQL is a smallint NOT NULL column, and is indexed. The created_date in PostgreSQL is a created_date timestamp without time zone NOT NULL column, and is indexed.

There is also another composite index:

CREATE INDEX product_created_date_type_id_idx
    ON product USING btree
    (created_date DESC NULLS LAST, type_id DESC NULLS LAST);	
Search using .Net Decimal - Run [1] - CreatedDate Desc - [19928.7159]ms
Search using .Net Decimal - Run [2] - CreatedDate Desc - [19132.9099]ms
Search using .Net Decimal - Run [3] - CreatedDate Desc - [19578.5421]ms
Search using .Net Decimal - Run [4] - CreatedDate Desc - [22294.7393]ms
Search using .Net Decimal - Run [5] - CreatedDate Desc - [19940.8091]ms

Search using .Net Int32 - Run [1] - CreatedDate Desc - [2673.4479]ms
Search using .Net Int32 - Run [2] - CreatedDate Desc - [2706.07]ms
Search using .Net Int32 - Run [3] - CreatedDate Desc - [3031.2587]ms
Search using .Net Int32 - Run [4] - CreatedDate Desc - [2584.9249]ms
Search using .Net Int32 - Run [5] - CreatedDate Desc - [2866.3663]ms

Search using .Net Double - Run [1] - CreatedDate Desc - [19027.7723]ms
Search using .Net Double - Run [2] - CreatedDate Desc - [19355.4194]ms
Search using .Net Double - Run [3] - CreatedDate Desc - [18845.8106]ms
Search using .Net Double - Run [4] - CreatedDate Desc - [19691.8726]ms
Search using .Net Double - Run [5] - CreatedDate Desc - [19467.7988]ms

Further technical details

Npgsql version: 4.0.3 PostgreSQL version: 10.5 Operating system: Windows 10

Other details about my project setup:

Have also tested using type_id as a .Net Short type and just as fast as Int32 type.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
YohDeadfallcommented, Nov 5, 2018

Npgsql doesn’t parse primitive numeric types. It changes the byte order using a single instruction and sends the value. The decimal type isn’t primitive, but its processing is fast too, but the timing depends on the provided value.

So as I said before it’s not a Npgsql problem. In your case you should swap columns in the index, so type_id will be first. Then PostgreSQL will use the index to filter values first and just read the required part of the index.

Check the query plans using EXPLAIN and compare them.

1reaction
rojicommented, Nov 7, 2018

In addition to all of @YohDeadfall’s correct comments above, it’s a pretty bad idea to benchmark this kind of thing with StopWatch. Consider making a quick benchmark with BenchmarkDotNet - it’s extremely easy to do and provides reliable measurements.

I’m sure that if you benchmark the right thing without any extra unrelated operations (e.g. parsing string to decimal), you’d find that Npgsql does things quite quickly. If you still think there’s a perf issue, please open a separate issue with a BenchmarkDotNet code fragment that demonstrates it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Is there a performance hit using decimal data types ...
If you're doing lots of calculations with the DECIMAL / NUMERIC values in the database, then performance can really suffer. This is particularly ......
Read more >
Supported Types and their Mappings
Write mappings​​ There are three rules that determine the PostgreSQL type sent for a parameter: If the parameter's NpgsqlDbType is set, it is...
Read more >
Npgsql: User's Manual
This section explains Npgsql usage in a .Net application (Windows or ASP.NET). If you have experience developing data access applications using ...
Read more >
Application Development Guide - Fujitsu Enterprise Postgres
Explains application development using embedded SQL in COBOL. ... improve performance if transferring large values from the database. Write Buffer Size.
Read more >
Npgsql.xml 1.0.0
Gets or sets the string used to connect to a PostgreSQL database. See the manual for details. </summary> <value>The connection string that includes...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found