Worth PostgreSQL. It has a table with a little more than 300 thousand lines.

If I execute such a request in pgAdmin, then it is executed in a fraction of a second (~ 300ms):

SELECT * FROM public."Movies" WHERE vote_count > 100 ORDER BY vote_average DESC LIMIT 10; 

If you perform a similar request in an ASP.Net Core application, the page is loaded for almost a minute (~ 50c), but if you do not use the database, but simply give the finished collection ala new Movie[] { ... } , then the download is almost instant.

 //в классе контроллера private IMovieRepository repository; public IActionResult Index() { return View(repository.Movies .Where(m => m.VoteCount > 100) .OrderByDescending(m => m.VoteAverage) .Take(10)); } //класс для работы с данными public class EFMovieRepository : IMovieRepository { private TMDbContext context; public EFMovieRepository(TMDbContext context) { this.context = context; } public IEnumerable<Movie> Movies => context.Movies; } //класс контекста public class TMDbContext : DbContext { public TMDbContext() : base() { } public TMDbContext(DbContextOptions<TMDbContext> options) : base(options) { } public DbSet<Movie> Movies { get; set; } } //конфигурация в классе Startup public Startup(IHostingEnvironment environment) { Configuration = new ConfigurationBuilder() .SetBasePath(environment.ContentRootPath) .AddJsonFile("appsettings.json") .Build(); } public void ConfigureServices(IServiceCollection services) { services.AddDbContext<TMDbContext>(option => option.UseNpgsql( Configuration["Data:Movies:ConnectionString"])); services.AddTransient<IMovieRepository, EFMovieRepository>(); services.AddMvc(); } 

I use Npgsql.EntityFrameworkCore.PostgreSQL

What is the problem? Maybe I have something wrong with the configuration or maybe the request should be made more correctly? Why is the SQL query in pgAdmin so many times faster than the query through the provider?

UPD: Changed method code to:

 public string Index() { var startTime = DateTime.Now; var movies = repository.Movies .Where(m => m.VoteCount > 100) .OrderByDescending(m => m.VoteAverage) .Take(10).ToList(); return (DateTime.Now - startTime).TotalSeconds.ToString(); } 

Returns an average of 17 seconds.

  • What does the page load? Perform a pure query, without any view, and see how much it worked. Then poprofiliruyte request, even if it takes so long to complete, maybe a completely different query is built there. - Monk
  • @Monk updated the question. Look in UPD please. - MrModest
  • @Monk and how to profile a query in Windows? - MrModest
  • @Monk by the way, in the debug logs of Visual Studio, the following SELECT "m"."id", <...>, "m"."vote_average", "m"."vote_count" FROM "Movies" AS "m" line SELECT "m"."id", <...>, "m"."vote_average", "m"."vote_count" FROM "Movies" AS "m" is it at every request the whole database asks for it? - MrModest

1 answer 1

 public IEnumerable<Movie> Movies => context.Movies; 

When accessing this property and getting the results of the query, the entire Movies will be loaded first, and then filtering will be applied.

The IEnumerable interface is in the System.Collections namespace. An IEnumerable object represents a data set in memory and can only be moved forward through this data. The query represented by an IEnumerable object is executed immediately and completely, so the data is received by the application quickly.

When executing the query, IEnumerable loads all the data, and if we need to perform their filtering, the filtering itself takes place on the client side.

https://metanit.com/sharp/entityframework/1.4.php

Replace IEnumerable with IQueryable . Then the selection will be made on the side of the database.

  • one
    Not really. Here, only one object is copied, and the loading of everything is already in ToList (). But the point is really in type. - Pavel Mayorov
  • @PavelMayorov yes, of course. - Zufir
  • Oh, damn .. It was worth guessing. Thank you, now it loads much faster. The request from UPD returns 0.2 seconds, and the View is launched quickly (as far as it is possible for the View). Plus I noticed that now the sql query does not pop up the entire database in the logs, but the filtered query) - MrModest