Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
220 views
in Technique[技术] by (71.8m points)

c# - Why does the Entity Framework generate nested SQL queries?

Why does the Entity Framework generate nested SQL queries?

I have this code

    var db = new Context();
    var result = db.Network.Where(x => x.ServerID == serverId)
        .OrderBy(x=> x.StartTime)
        .Take(limit);

Which generates this! (Note the double select statement)

SELECT
`Project1`.`Id`, 
`Project1`.`ServerID`, 
`Project1`.`EventId`, 
`Project1`.`StartTime`
FROM (SELECT
`Extent1`.`Id`, 
`Extent1`.`ServerID`, 
`Extent1`.`EventId`, 
`Extent1`.`StartTime`
FROM `Networkes` AS `Extent1`
 WHERE `Extent1`.`ServerID` = @p__linq__0) AS `Project1`
 ORDER BY 
`Project1`.`StartTime` DESC LIMIT 5

What should I change so that it results in one select statement? I'm using MySQL and Entity Framework with Code First.

Update

I have the same result regardless of the type of the parameter passed to the OrderBy() method.

Update 2: Timed

Total Time (hh:mm:ss.ms)    05:34:13.000
Average Time (hh:mm:ss.ms)  25:42.000
Max Time (hh:mm:ss.ms)  51:54.000
Count   13
First Seen  Nov 6, 12 19:48:19
Last Seen   Nov 6, 12 20:40:22

Raw query:

SELECT `Project?`.`Id`, `Project?`.`ServerID`, `Project?`.`EventId`, `Project?`.`StartTime` FROM (SELECT `Extent?`.`Id`, `Extent?`.`ServerID`, `Extent?`.`EventId`, `Extent?`.`StartTime`, FROM `Network` AS `Extent?` WHERE `Extent?`.`ServerID` = ?) AS `Project?` ORDER BY `Project?`.`Starttime` DESC LIMIT ?

I used a program to take snapshots from the current process in MySQL.

Other queries were executed at the same time, but when I change it to just one SELECT statement, it NEVER goes over one second. Maybe I have something else that's going on; I'm asking 'cause I'm not so into DBs...

Update 3: The explain statement

The Entity Framework generated

'1', 'PRIMARY', '<derived2>', 'ALL', NULL, NULL, NULL, NULL, '46', 'Using filesort'
'2', 'DERIVED', 'Extent?', 'ref', 'serveridneventid,serverid', 'serveridneventid', '109', '', '45', 'Using where'

One liner

'1', 'SIMPLE', 'network', 'ref', 'serveridneventid,serverid', 'serveridneventid', '109', 'const', '45', 'Using where; Using filesort'

This is from my QA environment, so the timing I pasted above is not related to the rowcount explain statements. I think that there are about 500,000 records that match one server ID.

Solution

I switched from MySQL to SQL Server. I don't want to end up completely rewriting the application layer.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's the easiest way to build the query logically from the expression tree. Usually the performance will not be an issue. If you are having performance issues you can try something like this to get the entities back:

var results = db.ExecuteStoreQuery<Network>(
    "SELECT Id, ServerID, EventId, StartTime FROM Network WHERE ServerID = @ID", 
    serverId);

results = results.OrderBy(x=> x.StartTime).Take(limit);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...