EntityFramework PostgreSQL GIST index for geography column - entity-framework-core

I'm trying to create a index, like this one:
CREATE INDEX example1_gpx ON example1 USING GIST (geography(geomcol));
Using EF codefirst, I did this on codefirst:
builder.HasIndex(x => new
{
x.GeoLocation
})
.HasMethod("GIST");
but I can't specify that it's a column of type geography.
How I can create this index using CodeFirst ?

Your index above seems to apply a geography() conversion to a geometry column; if so, it's an expression index (as opposed to a simple index over a column). The Npgsql EF Core provider doesn't currently support modeling expression indexes (see this issue), but you can always use raw SQL to create the index in migrations.
However, I'd recommend thinking why you're converting a geometry column into geography in an expression index; you may want to consider making your column geography instead. Another option is to have an additional generated column of type geography alongside the geometry column.

Related

EF Core Unique constraints with "NULL" values

The solution of Does EF Core allow a unique column to contain multiple nulls? works perfect with
Microsoft SQL Server but not with PostgreSQL. Is there a solution which works also with PostgreSQL (Npgsql provider) ?
You can simply use a filtered index to specify the WHERE clauses as you wish:
modelBuilder.Entity<Blog>().HasIndex(b => b.SomeInt)
.HasFilter(#"""SomeInt"" IS NOT NULL")
.IsUnique();
This creates the index as follows:
CREATE UNIQUE INDEX "IX_Blogs_SomeInt" ON "Blogs" ("SomeInt") WHERE "SomeInt" IS NOT NULL;

How to add a PostgreSQL GIN index on a uuid in Postgres 9.6

I'm trying to add a GIN index that includes a UUID in a Postgres 9.6 database. Technically it is a composite index, with composite GIN support coming from the btree_gin plugin.
I try to create the index with this statement:
CREATE EXTENSION btree_gin;
CREATE INDEX ix_tsv ON text_information USING GIN (client_id, text_search_vector);
but I get this error:
ERROR: data type uuid has no default operator class for access method "gin"
HINT: You must specify an operator class for the index or define a default operator class for the data type.
client_id is data type uuid and text_search_vector is a tsvector. I don't think the composite/btree_gin factor is actually relevant, as I get the same error trying to create the index on just client_id alone, but hopefully if there is a solution to this, it is one that will work with a composite index also.
I found PostgreSQL GIN index on array of uuid , which seems to suggest that it should be possible (if an array of UUIDs can be done, then surely an individual UUID can be done). However, the solution there was pretty opaque to me - it's not immediately obvious how to modify this solution to support a single UUID.
I would prefer a solution that doesn't involve casting the UUID to another type in the index or in another column, as I would rather not have to write specialized queries with casts in them (we are using django ORM to generate queries atm).
It is possible for GIN indexes. But not before Postgres 11, where it was added. The release notes:
Allow btree_gin to index bool, bpchar, name and uuid data types (Matheus Oliveira)
So the simple solution is to upgrade to Postgres 11. This should be good news for you:
April 9, 2019: Cloud SQL now supports PostgreSQL version 11.1 Beta
Or, in many cases you can alternatively use a GiST index, for which the same was introduced with Postgres 10, already. The release notes:
Add indexing support to btree_gist for the UUID data type (Paul Jungwirth)
Related:
How to use uuid with postgresql gist index type?
If neither is an option, you are back to what you wanted to avoid:
casting the uuid to another type in the index
You can create an expression index on a (consistent!) text representation or, theoretically, on two bigint columns derived from the uuid. But the first makes the index considerably bigger and slower and the second creates much more complication ...
The syntax of the cast is simple enough though: uuid::text. In an index expression that requires an extra set of parentheses. With the additional module btree_gin installed:
CREATE INDEX ix_uuid_tsv ON text_information USING GIN ((client_id::uuid), tsv);
Related:
Postgres using an index for one table but not another
What is the optimal data type for an MD5 field?
Would index lookup be noticeably faster with char vs varchar when all values are 36 chars
Or you could backport the feature from Postgres 11 - which is not an option with a hosted service like Google Cloud SQL for PostgreSQL as you mentioned in a comment. And I hardly see the use case where one would be skilled enough to implement the backport, but not to upgrade to Postgres 11.

How to map a column to JSONB instead of JSON, with Doctrine and Postgresql?

In my project I'm using Doctrine doctrine 2.5.4/postgres 9.5. I'm trying to add a jsonb field using YAML:
fields:
obj: json_array
This gets interpreted as a json column type (and not jsonb). The specification notes about picking up json or jsonb:
Chosen if the column definition contains the jsonb option inside the platformOptions attribute array and is set to true.
But platformOptions doesn't seem to work (tried to add it below obj, at the top... with no success). How can I add a jsonb field?
This is supported by doctrine/dbal v2.6+ (it requires PHP 7.1). All you need to do is use json_array and set options={"jsonb"=true} I tested this on doctrine/dbal v2.6.3
This is what it looks like in PHP format:
/**
* #ORM\Column(type="json_array",nullable=true,options={"jsonb"=true})
*/
private $details;
and it creates a query such as (for an existing table):
ALTER TABLE mytable ADD details JSONB NOT NULL;
More details about type mapping can be found at Doctrine mapping matrix.
Use boldtrn/jsonb-bundle, it provides a jsonb doctrine type as well as custom functions to access the special operators provided by the PostgreSQL jsonb data type.

PostgreSQL indexes for hstore boolean attributes

I have an hstore column called extras and I have defined there many attributes some of them are boolean and I would like to index some of them for example extras->'delivered' in this case which would be the best way to index some of these attributes.
If you answer could you tell me if your technique applies for decimal or other types.
Thanx.
Indexing individual keys in a hstore field
The current hstore version doesn't have typed values. All values are text. So you can't directly define a "boolean" index on an hstore value. You can, however, cast the value to boolean and index the cast expression.
CREATE INDEX sometable_extras_delivered_bool
ON sometable ( ((extras->'delivered')::boolean) );
Only queries that use the expression (extras->'delivered')::boolean) will benefit from the index. If the index expression uses a cast, the query expressions must too.
This b-tree index on a hstore field will be less efficient to create and maintain than a b-tree index of a boolean col directly in the table. It'll be much the same to query.
Indexing all keys in a hstore field
If you want a general purpose index that indexes all hstore keys, you can only index them as text. There's no support for value typing in hstore in PostgreSQL 9.3.
See indexes on hstore.
This is useful when you don't know in advance which keys you need to index.
(Users on later, pre-release at time of writing versions of PostgreSQL with the json-compatible hstore version 2 will find that their hstore supports typed values).
Reconsider your data model
Frankly, if you're creating indexes on fields in a hstore that you treat as boolean, then consider re-thinking your data model. You are quite likely better off having this boolean as a normal field of the table that contains the hstore.
You can store typed values in json, but you don't get the GIN / GiST index support that's available for hstore. This will improve in 9.4 or 9.5, with hstore 2 adding support for typed, nested, indexable hstores and a new json representation being built on top of that.
Partial indexes
For booleans you may also want to consider partial index expressions where the boolean is a predicate on another index, instead of the actual indexed column. E.g:
CREATE INDEX sometable_ids_delivered ON sometable(id) WHERE (delivered);
or, for the hstore field:
CREATE INDEX sometable_ids_delivered ON sometable(id) WHERE ((extras->'delivered')::boolean);
Exactly what's best depends on your queries.

Use of DB2 Indices with several columns

We are trying to locate a performance problem and wondering if an index is being used.
We have a table with a composite key, "ID" and "Version", both integers.
We have a select that tries to find the max of "ID". (This is done via Entity framework if it makes a difference).
Will this use the index or will it do a table scan?
If the ID column is defined as the first part of a multi-column index, then DB2 will use that index to determine the MAX(). It will still probably try to use the index if you did a MAX(VERSION), but if you have a very large table, this may take quite a bit of processing.
You can confirm this using the explain facilities (link is for Linux/Unix/Windows 9.7).