How to speed up Doctrine in routine statements like getting collection or related data from object?
What's better if i want to get list with related tables data. Native sql in doctrine or using doctrine_query?
Several things could help. I've noticed substantially better performance with Doctrine 2.
Working with Doctrine 1.2 one of the best things you can do is hydrate to as simple of a structure as you can. I had reports that I could definitely not hydrate to record on but worked find if I hydrated to scalar or array.
Other than that, make sure you use DQL instead of the magic finders to load objects. Using DQL will help ensure you load all parts of your object graph that you need in one query (see lazy loading).
Hope some of this helps.
Related
I am working on a project that uses the ORM heavily instead of model relationships in the controller to get to the data (for eg: using leftJoins instead of establishing proper model relationships using hasMany etc and then retrieving through that)
My question is actually to do with the performance. Is using model relationships to access data faster than using leftJoins? I am not sure if Laravel actually does perform a leftJoin under the hood.
I am on a tight schedule so I want to decide if its actually worth trying to refactor the code to use the model relationships and if it would provide gains in performance?
Thanks in advance
Laravel anbd Eloquent may execure queries differently using the relationship as opposed to the join. You can use the barryvdh/laravel-debugbar to see query execution.
My observation is that Laravel will tend to use two queries instead of a join if possible. It will execute the first query and then using the IDs returned from that query execute a second query on the "joined" table as a "where myID in (1,2,3,4,5..)" and then stitch the results together.
As others have suggested, building up a quick test and seeing what works best in your environment would be the best bet. I prefer to use the relationships as much as possible becuase you can easily read what your code is doing.
Joins and relationship are not opposite of each other. Relationships are for ease of development, cleaner, more readable code, easy to maintain. Performance difference is almost non existant unless you are developing a data miner of some sort.
Edited
If you are focusing on performance, you can work on implementing caching in a efficient way.
i want to load an entity in my Controller, but dont want that the entity contains all fields. I did that before with the Jms-Serializer, where you can use the Groups Annotations, to avoid loading special fields. But i there you have to serialize your object to json/xml etc.
And i dont want it serialized, i just want that groups function. I searched this site and the internet, but didnt found any solution for my problem.
Hope that someone understand what i mean and got an idea :)
There are a couple of possibilities:
Use partial objects (which will deliver objects where only specified attributes will be filled during hydration): http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/partial-objects.html#partial-objects
This is dangerous and you should be extra careful, because it looks like a fully loaded entity from all perspectives. You have to know why a field is null - just because it's null or because it simply hasn't been filled during hydration.
Don't hydrate objects but query for an array as hydration result (by that again you can specify which array keys you would like to get back): http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#array-hydration
Use this for performance-sensitive queries where you need a lot of read-only data and complex joins. But be aware that you don't have any entities you can manage with Doctrine (e.g. updating, deleting etc.).
Use DTOs which are objects but non-Doctrine-managed entities, there again you can specify what you would like to get hydrated with the NEW syntax: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#new-operator-syntax
Basically the same advise as in 2) but this time you'll get objects. So you can use all your OOP wisdom.
Create your own custom hydration mode - there you can define on your own how entities should be hydrated: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#custom-hydration-modes
Very advanced level. Only useful if you need a special hydration mode for several entities and really no other option delivers at performance and quality as you require it.
You can use partial objects, but you should be careful. For example:
$q = $em->createQuery("select partial u.{id,name,otherField} from MyApp\Entity\User u");
You can read more here: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/partial-objects.html
The tutorial of zend framework show that I can use Zend\Db\ResultSet\HydratingResultSet to return a model object using the dbAdapter ,select query and a model prototype. But in most case writing the website code I use multi-table query and the hydrator can not fix this problem but just a single table query. How should I deal with this kind of problem.
hydrator doc
And this problem can also happen when encounting the pagination which also only take one prototype.
paginator doc
Depending on the query, you might need a custom ResultSet that knows how to deal with the multi-row potential of a multi table query, and mapping that dataset appropriately.
Additionally, if you find yourself getting into very advanced object relationships with Zend\Db, that might be the time to start considering Doctrine2 (or a similar ORM).
Ok, so I'm trying to figure out eager loading to improve application performance. I'm working on a service database, but am having some problems. Here is my code
$service_data = Client::join('service_requests','clients.id','=','service_requests.client_id')
->join('service_request_comments','service_requests.id','=','service_request_comments.service_request_id')
->whereNotNull('service_request_comments.time')->with('service_requests')->with('service_requests.comments')->get();
The query does properly pull the data, but it loads ALL service_requests and service_requests.comments into the first client_object, instead of loading a client object with the service_requests objects and then loading the service_request objects with the appropriate comments.
Each of these relationships are one to many...
...A client can have many service_requests
...A services_request can have many comments
...and by extention...
...A client can have many comments
I tried using the constraints, but that just gave me a couple dozen 500s with various syntax. Could somebody tell me what I'm doing incorrectly?
Don't use joins if you're doing eager loading. You're essentially combining Query Builder commands with Eloquent features, and the two are conflicting. Something like this should get the same thing (skipping the where constraint for now):
$service_data = Client::with('service_requests.comments')->get();
Note that the nested with() request will automatically eager load service_requests and then their comments.
If you need the query on the comments relationship, there are a couple ways to do so, and I don't want to make assumptions about exactly what you're using for (or if it's necessary at all), so I'll skip that for now.
Can someone provide me a couple clear (fact supported) reasons to use/learn DQL vs. SQL when needing a custom query while working with Doctrine Classes?
I find that if I cannot use an ORM's built-in relational functionality to achieve something I usually write a custom method in the extended Doctrine or DoctrineTable class. In this method write the needed it in straight SQL (using PDO with proper prepared statements/injection protection, etc...). DQL seems like additional language to learn/debug/maintain that doesn't appear provide enough compelling reasons to use under most common situations. DQL does not seem to be much less complex than SQL for that to warrant use--in fact I doubt you could effectively use DQL without already having solid SQL understanding. Most core SQL syntax ports fairly well across the most common DB's you'll use with PHP.
What am I missing/overlooking? I'm sure there is a reason, but I'd like to hear from people who have intentionally used it significantly and what the gain was over trying to work with plain-ole SQL.
I'm not looking for an argument supporting ORMs, just DQL when needing to do something outside the core 'get-by-relationship' type needs, in a traditional LAMP setup (using mysql, postgres, etc...)
To be honest, I learned SQL using Doctrine1.2 :) I wasn't even aware of foreign-keys, cascade operations, complex functions like group_concat and many, many other things. Indexed search is also very nice and handy thing that simply works out-of-the-box.
DQL is much simpler to write and understand the code. For example, this query:
$query = ..... // some query for Categories
->leftJoin("c.Products p")
It will do left join between Categories and Products and you don't have to write ON p.category_id=c.id.
And if in future you change relation from one-2-many to let's say many-2-many, this same query will work without any changes at all. Doctrine will take care for that. If you would do that using SQL, than all the queries would have to be changed to include that intermediary many-2-many table.
I find DQL more readable and handy. If you configure it correctly, it will be easier to join objects and queries will be easier to write.
Your code will be easy to migrate to any RDBMS.
And most important, DQL is object query language for your object model, not for your relational schema.
Using DQL helps you to deal with Objects.
in case inserting into databae , you will insert an Object
$test = new Test();
$test->attr = 'test';
$test->save();
in case of selecting from databae, you will select an array and then you can fill it in your Object
public function getTestParam($testParam)
{
$q=Doctrine_Query::create()
->select('t.test_id , t.attr')
->from('Test t ')
$p = $q->execute();
return $p;
}
you can check the Doctrine Documentation for more details
Zeljko's answer is pretty spot-on.
Most important reason to go with DQL instead of raw SQL (in my book): Doctrine separates entity from the way it is persisted in database, which means that entities should not have to change as underlying storage changes. That, in turn, means that if you ever wish to make changes on the underlying storage (i.e. renaming columns, altering relationships), you don't have to touch your DQL, because in DQL you use entity properties instead (which only happen to be translated behind the scenes to correct SQL, depending on your current mappings).