-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Another joinWith() approach #1618
Comments
|
So as i see the aspect of separation is:
Ok, fine. Such DB solutions can ignore |
The advantage of separation is that it is clearer - when you see the term |
We don't want to go for the 1.1 approach because it involves complicated table/column aliasing, which is not trivial to implement and is also tricky to use. The issue pops up because people are accustomed to the 1.1 approach which mixes the concept of data fetching and data filtering. In practice, it's very possible that you join with some relations while eager loading some other relations. Data fetching and filtering should be separated as designed in 2.0. The |
I did not understand the need |
@slavcodev |
@qiangxue So the |
I agree that this should be a separate method but I don't like @qiangxue explanation. You shouldn't state that data fetching and filtering should be separated. I think most database system, SQL or not, are faster in performing those tasks than PHP. Even NoSQL systems are advertised as providing an efficient map-reduce filtering method. I think the most important cons are:
The pros are:
I'm not listing aliasing as a con. Personally I never had trouble with that. Even if it's hard to implement it doesn't state anything about good design. I like when three types of data loading are defined:
Actually the terms lazy and eager should be well recognized by devs, as it is common to a lot of ORMs. Now introducing them to with and together creates the confusion. I'd say that eagerWith would be better than joinWith, even gramatically. Recently I extensively audited the ActiveFinder from Yii 1 to add support for MANY_MANY through relations. It's complex, but complete. It's a shame to throw it away. I find it very useful and I build some tools around it. To conclude, I think it's a very important feature and if it's not done well it can drive a lot devs away from Yii 2. PS. Actually, the best solution is to use subqueries instead of separate queries and passing list of PK values. That allows cross-referencing tables with some limitations. This is just a crazy idea, I'm going to think about it more in near future when browsing the code. |
@creocoder Yes. @nineinchnick The biggest drawback of AR in 2.0 is the potential performance issue for eager loading (even this may not be very true). Other than this, it has all the pros you listed for AR 1.1. As you may have found out, the current AR 2.0 design allows it to be supported by NoSQL and other non-relational DBMS, and it even supports relation between ARs from different types of DBMS. Regarding the term "eager" and "lazy", the rule for AR 2.0 is very simple: if you use |
You're right, it's just a question what terms should we use for eager and eager-er, that is the two eager loading methods I mentioned. I'd just like to address that the current method of eager loading by passing a list of PK values to a second query feels dirty. I will look into it and try to find a solution. |
You confuse eager loading with query strategy. Eager loading is wide term which related not only to ORMs. Both |
Not all DBs support subqueries. Also there is some troubles with subqueries in some legacy mysql versions for example. |
We had the similar thought initially when we were redesigning AR. But our tests and investigation found that it is not that bad. It actually has many benefits, including the support for relational queries for NoSQL DBs. Performance wise, there is no proof that it would be worse than join (it may be faster in fact.) The only limitation is when you have too many PKs returned, the queries for related records could be too long to be accepted by DBMS. However, this is very uncommon. |
@qiangxue Another idea for this: $items = MyModel::find()
->with([
'relation1' => function ($query, $options) {
$options->together = true;
$options->joinType = 'INNER JOIN';
},
'relation3' => function ($query, $options) {
$query->andWhere(...);
$options->together = true;
},
'relation4',
'relation5',
])
I remember times when |
@qiangxue And little more here:
Fine, lets name this more abstractly as
strategy ? |
@creocoder I'm interested to see your profiling results which compares non-join and join queries. I have pretty much explained why we chose the current design and method names in my previous replies. I think we should spend time repeating the same debate again. |
@qiangxue Ok will create profiling tests then with different environments: local sql server and remote sql server. |
Cool. Make sure you disable query cache when testing: http://dev.mysql.com/doc/refman/5.1/en/query-cache.html |
No, most of them do not have the possibility to retrieve data in a join-like query. Querys do return records of one type in most cases and if it is multi type then the way the records are fetched is different from relation way but like cross type search or something like that. redis does not have it because it is key value only. elasticsearch can only fetch parent-child relation in one query. Not sure about Mongo. |
Is there any way to load eager data "with" or 'joinWith' for ORM by another database ? For example In model Company I have
City is a model that has already configured to another database using:
But is not work, the generated query does not include the name of another_database.city_table.id in condition LEFT JOIN, so a database exception occurs I tried
But although the generated query is corrected the data of city for each company loaded by lazy method |
So the best solution I found is
So what is your opinion ? @SilverFire |
If you want to |
Suggest
joinWith()
removing and making onewith()
method with following signature:to make API more logical.
The text was updated successfully, but these errors were encountered: