Open DanielBertocci opened 6 months ago
Yes, if you do @iot.id eq '1'
you explicitly tell FROST to compare the id with a string, so it has to cast the id to a string.
You should use @iot.id eq 1
Or, even simpler, just GET v1.1/Datastreams(1)/Observations
I have done some experiments with that join, and it makes no significant difference in recent versions of PostgreSQL. Though recent versions of FROST will try to optimise it out.
First of all, thank you because you gave me an immediate way to solve the issue we had.
This issue was really hard to find out, it needed some steps to realize that with that query, we didn't take advantage of the indexing.
I wonder if FROST could take special care about IDs, especially with plugins_coreModel_idType
set: it knows what is the expected type for the IDs and I would expect the cast of the query parameter to the idType
more than the current behavior.
A more explicit behavior could be to throw an error, claiming that it is not possible to use a string value when the id is bigint.
I see a risk that, for a matter of quotes in OGC STA query, FROST doesn't take of the advantage of the DB optimizations.
What do you think?
This problem is not limited to ID fields, it can happen any time a comparison is made between different types. One of them will have to be cast to the other, and since the only cast that is guaranteed to succeed is the cast to string, that's what FROST does. The same thing happens when filtering on one of the times, and quoting the time-constant in the URL.
The fact that in this specific case that means an index can't be used is something FROST doesn't know, since FROST doesn't know which fields have indices.
In theory, since the "other" field is a constant, FROST could try to see if that string constant could be converted to the non-string type, before taking the route that is guaranteed to work. That may be worth looking into...
But this will lead to confusing behaviour when comparing result values to a quoted number, since result has a string-representation, so no casting is needed. Thus comparing IDs to a falsely quoted number (using gt
or lt
) would result in the behaviour that the user expects, but comparing results to a falsely quoted number would not... For IDs '2'
would be smaller than 11
, but for results '2'
would be larger than 11
...
Issue Description
I use
plugins_coreModel_idType
set toLONG
for the system and FROST correctly creates tables with IDs bigint. I recently faced a performance issue on query observations, the system turned to be really slow, it could be one of the new updates of FROST but I am not sure.What causes the issue
I have enabled query logging and I identified the query causing the issue. When observations are queried with the query
Observations?$filter=Datastream/@iot.id eq '1'
FROST generates the following query:The key of the issue is
Using
plugins_coreModel_idType
set toLONG
,DATASTREAM_ID
is a bigint and this cast messes up with the indexing and partitioning in the table, I imagine it cannot perform a proper comparison because of the different type. If I remove that cast, the query becomes more than 20 times faster (4 seconds -> 0.2 seconds)Expected behavior:
What I would except is that this cast is dependent on the setting of
idType
, and in my specific case the cast to bigint.How to reproduce
I have used the docker compose on FROST scripts with
plugins_coreModel_idType
set toLONG
.docker-compose.yaml
Additional notes
I see also a
JOIN
that is not needed, only with $expand and accessing nested fields but it is not the case for the proposed query, I wonder if there is a way to optimize that too.