Postgres Gin index definition in Spring JPA - postgresql

I have created a Postgres Gin index in a Spring Boot JPA application to allow fast text based search queries on a Text type column. Is it possible to define it using any native command that would execute on application deployment so I don't have to remember adding it to the table manually every time I deploy the microservice?
Using #Index in the #Table for the entity creates btree indexes.
This problem is also for a Hash type index I need. Btree is fine but Hash will be a bit faster for my queries so I'd like to automate those Gin & hash creation.

Related

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.

Postgresql - Optimizing creation of several indexes on one big table

What's the best way to create multiple indexes on one very large table (hundreds of Gb).
Currently I have to execute queries like that
create index A on myBigTable (a) using btree ;
create index B on myBigTable (b) using btree ;
create index C on myBigTable (c) using btree ;
....
It takes a very long time. PG has to read all the data from the table several times.
When index on column A is in creation, it prevents from creating an index on column B at the same time.
So, is there a way to optimize the time (and resources consumption) to create all indexes on the same table?
If not possible to really optimize currently, is it something planned for a near future?

Is there any benefit using index or foreignKey in slick table schema?

Should i use indexes and foreignKey in slick schema table? Is there any benefits like performance or query planner?
We are using Flyway DB migration tool so we wont use this schema with schema.create
Foreign keys in slick schema table would help you in two cases
first is from slick doc
...foreign key can be used to navigate to the referenced data with a join. For this purpose, it behaves the same as a manually defined utility method for finding the joined data ...
And if you generate DB schema using slick (for example, in tests)
Setting up indexes help you to fasten your searching(data retrieval), but slows down insertion. So you need to decide according to your requirement what you want. If there is more searching and data in DB is huge you should go for indexing.
Foreign keys, on the other hand, are used to maintain the relationship between different tables which are used for join in relational DB. Adding foreign keys will not have any impact on performance.
You can get more insight on indexing here -> Indexing,
And for foreign key here -> Foreign Key

Talend, Postgres and sequences

I have a JPA application and associated Postgres schema that was designed with a single sequence table (not a sequence). I am trying to populate several tables using Talend tPostgresqlOutput. These tables have keys that are sequenced by the JPA application. I am at a loss to work out how to read a sequence number from the table, update it and then use the sequence number to key a record on an insert with Talend. I can work it through with a sequence, but this is a table.

How to annotate unique constraint with WHERE clause in JPA

I need to use these unique constraints in PostgreSQL
CREATE UNIQUE INDEX favorites_3col_uni_idx
ON favorites (user_id, menu_id, recipe_id)
WHERE menu_id IS NOT NULL;
CREATE UNIQUE INDEX favorites_2col_uni_idx
ON favorites (user_id, recipe_id)
WHERE menu_id IS NULL;
The first one I annotate in JPA:
#Table(uniqueConstraints= {
#UniqueConstraint(name="favorites_3col_uni_idx", columnNames = {"user_id", "menu_id", "recipe_id"})
})
But, ¿it is possible to annotate in JPA the second unique index?
Thx.
You appear to want to create partial indexes (CREATE INDEX ... ON ... WHERE) using JPA constraint definitions.
These are fairly PostgreSQL specific, and aren't specified by JPA. You will need to use native syntax to create them. I don't believe JPA offers any features for index definition.
You cannot use a unique constraint for this purpose because unique partial indexes are not unique constraints. Partial unique indexes cannot be created with CONSTRAINT constraint_name UNIQUE(columns) in PostgreSQL. It's only an implementation detail that PostgreSQL creates a unique index for a unique constraint at all.
See:
Specifying an Index (Non-Unique Key) Using JPA
JPA: defining an index column
Some JPA providers offer extension annotations specific to that JPA provider that add features for running native DDL scripts, defining indexes with annoations, etc. Since you haven't mentioned which JPA provider you are using I can't tell you more. Here's the documentation for EclipseLink index DDL; this will not work if you are using Hibernate, OpenJPA, or something other than EclipseLink.
A JPA standard workaround is to check for the presence of those indexes during startup by querying pg_catalog.pg_index. If you don't find them, use an EntityManager native query to send the appropriate native SQL CREATE UNIQUE INDEX commands. A #Startup #Singleton bean is useful for this sort of task if you're using EJB3.1. See the PostgreSQL documentation for the structure of pg_catalog.pg_index. To just check if an index of a given name exists, run:
SELECT EXISTS(
SELECT 1
FROM pg_index
WHERE indexrelid = 'public.indexname'::regclass
);
Note that the above query does nothing to verify it's the index you expect, but you can do that with some additional checks. Just examine the contents of pg_index after creating the index so you know what to test for. I don't recommend trying to check for any particular value of indpred; just make sure it isn't null.