One of the least explored field in Entity Framework is what happens to your queries when you work with a large set of entities and hierarchies.
When querying an entity that has a -to-many relations, the generated query is a simple query - contains only the fields of that entity.
When querying an entity that has a -to-1 relations (1:1, N:1, 1:0..1 ...), the generated query contains the fields of the queried entity and the keys of every -to-1 relations. This was made to allow the related entities to automatically be referenced to already loaded entities (in case the related entities were loaded before, they will be automatically referenced, without the need to reload data from the DB).
Note that this doesn't occur for -to-N relations (1:*, 0..1:*, *:*), probably because they tried to avoid selecting to many rows.
Another problem arises when the related entity is a base class to a hierarchy of entities - in this case, when the main entity is queried, the generated SQL will contain "left joins" for every derived type of the referenced entity and not only the referenced type (the base type) itself. When dealing with a large hierarchy, this can cause your queries to become very slow. For example, I had a model with 15 derived types, which caused querying a simple entity related to the base type to take over 1 minute to execute (querying 15 left joins).
If you encounter this problem, there is a simple solution that can be applied to some cases - if you only need that specific entity, with neither of the relations and you don't plan to change it further on, use the NoTracking enum of the MergeOption property (part of the ObjectQuery type). When the NoTracking options is set, the entity is loaded but isn't attached to the context, making the generated SQL contains only the fields of that entity without the keys of the related entities.
Generated SQL for loading a person object (Notice that the address table isn't queried):
[Limit1].[C1] AS [C1],
[Limit1].[Id] AS [Id],
[Limit1].[FirstName] AS [FirstName],
[Limit1].[LastName] AS [LastName],
[Limit1].[Age] AS [Age],
[Limit1].[Id1] AS [Id1]
FROM ( SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
[Extent1].[Age] AS [Age],
[Extent2].[Id] AS [Id1],
1 AS [C1]
FROM [dbo].[Person] AS [Extent1]
LEFT OUTER JOIN [dbo].[Cars] AS [Extent2] ON [Extent1].[Id] = [Extent2].[PersonId]
) AS [Limit1]
Generated SQL after setting the MergeOption:
SELECT TOP (1)
[c].[Id] AS [Id],
[c].[FirstName] AS [FirstName],
[c].[LastName] AS [LastName],
[c].[Age] AS [Age]
FROM [dbo].[Person] AS [c]