cincura.net wrote:
Otis wrote:
I'm sorry, but I don't buy that. The parameter is declared, it's typed. You're saying that the database doesn't know the type of the parameter defined right there in the query?
Yes. Because the parameter descriptions are sent after the query is sent and processed.
Otis wrote:
What if I select a value into an output parameter in the projection? I don't have to cast it in any shape or form.
You mean like "select @p = 1 from ..."? You can't do that in Firebird. Parameters in *queryp are strictly input-only. Though you can do it in PSQL (and in some cases like in RETURNING statement), but then the parameter is bound to metadata of the query or definition itself (in PSQL "declare parameter ...").
Oh, indeed, my bad (mondaymorning!), Firebird has only input parameters in general...
Otis wrote:
And what about the value in the parameter? It's an int. Why do I have to cast the parameter, with the value which is an int, to int?
Because server doesn't know the value while query is processed and data structures are allocated. With the explicit cast you'll tell the type.
OTOH if you'll wrap the query i.e. in EXECUTE BLOCK and declare the parameters in advance in header, Firebird will be OK with that.
I think that's a bit overkill for this. We'll see what we can do. If nothing works we can go for the explicit cast to int instead of the normal constant. It's a bit more SQL for other databases though...
Otis wrote:
Because our engine doesn't insert constants in SQL, ever.
Good. I was just trying to offer some simple way.
I know.
In this particular case we could go for this though, as the constant is known, it's always numeric and it's generated by the engine. We'll do some tests.
Otis wrote:
No this isn't a problem. See it as this: EF always uses the join, not 1 query per node. (our system works similarly as prefetch paths). This crumbles down very quickly as joins make the end result very big in most cases (due to duplication of data) and very wide (due to all the joined columns).
We fetch each nested query as a separate query and merge internally. So if you fetch nested queries using 2 or more paths or as a 1:n, it's already much more efficient (we also use efficient IN clauses for filtering) than joins.
Yes, if you're dumb and you you're dot-jumping through a lot of objects, you're effectively fetching whole database. Anyway, it's OK for me, the application will run on server, where the latency is low, but for desktop etc., I have to remember the behavior and keep eye on it.
Not necessarily slower. We do all our testing on a database in the network and it's in general more efficient to do it this way, also over a network. The only situation where things could be equal with a join is with just 1 nested query related over a m:1 relationship. Though the projection engine gets more complex because of that and as this is generic code (as in: it works with all kinds of queries), it's not possible to decide 'oh for this query do it this way, for that query do it that way), so we opted for the way which is more efficient (also over the network) in most cases.
I doubt the query will be much slower over the network though, as it's done this way:
- first the parent is fetched, i.e customer
- the customer rows are used for producing the filter for the nested query, i.e. address
- only the addresses which match with the customers fetched are read
- merge takes place using hashing, same as inside DB
so the amount of data passed over the network is equal or smaller (in case of 1:n, m:n) to the amount of data passed over the network when using a join. The calling code is doing a bit more because it has to merge the resultsets, but that's done very efficiently.
As your nested query is a m:n relationship, your join resultset will have a lot of duplicate rows for the parent. This could increase the amount of data returned to the client a lot. So it's not said that a join is more efficient.