Slow performance calling DbContext.Database.CompatibleWithModel - entity-framework

we're running EntityFramework (6.1.3) Code-First with about 40 migrations on a small database (490 MB) on SQL Azure.
While extending our release process with a check to call Database.CompatibleWithModel to verify if the database is up to date, I've found that our test instance got rather slow: this call will take up to 2 minutes to complete. On our production environment and locally this is less than a second!
I've run a SQL profiler job locally and found only 3 statements that get fired on the the database:
Does the database exist?
How many migrations are in the database?
What is the migrationId and model of the last migration?
When I run these statements on the slow environment it completes within a second, just like on production. This indicates that the database is not an issue.
Does anyone have an idea were to search for the reason of the slow performance? Does EF calculate the hash locally on runtime and then checks that against the model in the database?
Can I find out how long it takes to hash?
I've checked the settings on the Azure Database to check against the CompatibilityLevel of the database, after finding a post that the EDMX editor is slow with the new cardinality estimator, but this setting seems to have no effect.

Related

Azure Database, EF, Time out issues

I have taken over an existing MVC website which uses entity framework and hangfire and is hosted on Azure and uses Azure database. Every so often the website times out.
I'm new to Azure portal, entity framework and hangfire.
If I increase the DTU's it clears the timeout issues?
I'm looking for ways of how to diagnose why the website times out. I have added error logging using elmah and checked hangfire but this doesn't give me any further information.
Is there anything in azure portal that can help?
If it "times out" and if "increasing DTU resolves timeouts" and these observations are true (I think it's on you to really convince yourself this is absolutely true, don't make this assumption lightly) then the usual and obvious candidate is "a slow sql query". Entity Framework is often used with linq to create sql queries without writing sql. These queries are often fine for very simple tasks, such as someData.Where(x=>x.Id == 1).First(), however, if linq is used to join tables, or create complex associations, the generated sql can become monstrously bad, from a performance perspective. You can add logging to write out the sql generated by linq, or you can try to trace the database to see what sql is running on it. If tracing is out of the question, there are still meta queries you can use to view things like cached query plans and SQL Server can give you estimated costs and cached execution counts.
You can still hang yourself without using linq. You can still use stored procedures with EF. Way too many developers are naive about SQL performance still; you need to comb over your back end and learn the schema, the stored procedures; inspect the sql contents of everything. Check for any database triggers (easy to miss). Red flags are subqueries, too many joining, too many results from a query, lots of string manipulation in a query, joining tables on strings, or XML/JSON-based SQL work.
Be aware that "slow sql queries" will become slower when load is high. And when slow sql queries build up, they only take more time to resolve. This can also cause debilitating table locking, depending on the nature of the query.
But queries can be performant and still cause locking. ie One table is being written to often and it's blocking other writes or reads from that table. This is a little harder to diagnose, but you can figure it out by carefully inspecting logs of database calls and how long they take to execute. There are also sql queries you can run on the database to diagnose long-running queries, or what tables are locked at a given point in time.
Finally, check for any back end webjobs for your application. If timeouts occur at reoccurring days or times, then somebody's batch SQL could be blocking your production database from being read.
But this is all speculation. I think you need to do more research to determine what is actually causing the site to become unresponsive. If you can log response times for common queries, you can rule out SQL-based latency as being the culprit or not and work from there. There's nothing inherently "amiss" about any of the technologies you specified.
If queries are perfomant but still causing issues, a long term solution is to add something like a message queue and batch your sql work intelligently, or just make the database work asynchronous and not block the UI.
You should correlate any logged timeouts with azure's monitoring. Azure can give you CPU/RAM/page visits and such on the dashboard.
SQL Azure is a bit of a different beast. It doesn't have the on-demand performance of a dedicated DB unless you're prepared to throw serious $$ at it. And even then ...
EF, when written for well can perform quite well. When written poorly it can be a dog, and those problems are compounded on a platform like SQL Azure.
The first thing is to check that your EF contexts are set up to use an execution strategy suited to Azure: https://learn.microsoft.com/en-us/ef/ef6/fundamentals/connection-resiliency/retry-logic
The next thing would be to see what kinds of SQL tracing you can run on Azure. Tracing is essential to see what EF is doing behind the scenes. I'm not familiar with tools available for Azure, in my case my Azure experience was running SQL Server on VMs because SQL Azure was too immature, not HIPAA compliant at the time, and expensive for the DTU estimates we were able to get. Worst case, can you restore an database backup into an SQL Server instance and point a copy of your application environment temporarily at that to run through common usage scenarios? Using an SQL Trace you can pick up on exactly when and how often EF is executing queries, and what queries it is executing.
Things to look at:
How many queries are running? If you are loading a set of records and expect one query, are there a whole heap of queries getting sent? This would indicate lazy-load calls being triggered.
What queries are being run? Is it selecting a lot more fields than are being displayed? This would be potentially a case where entire entities are being loaded where a .Select() could be used to reduce the amount of data. Perhaps even the case where entire sets of entities are being loaded that aren't relevant to what is displayed/done, such as cases where someone is using .ToList() prior to just doing a .Count() or .Any() or doing a .FirstOrDefault() just to do a != null check.
Is the database properly indexed? Copy some of the heavier queries into SQL Manager and execute them with an execution plan. Are there indexing suggestions?
The common sins of developing with EF and other ORMs boil down to "pulling too much, too often." It's surprising how many clients I've worked with have development teams that have not used a profiler to inspect their ORM use efficiency. (and I'm talking 0% so far.)

Is it mandatory to run Database Designer for every schema in HP Vertica?

Constantly i have been hitting with Resource pool allocation error after creating several tables in new schema.
After running the Database Designer in vertica for particular schema with all tables the queries are running fine.
Kindly help me to understand the concept.
The Database Designer is optional; you don't have to use it at all. Using it helps you optimize your physical layout, and if you're having trouble with resource-pool allocation it sounds like you might benefit from that.
From the documentation:
The HP Vertica Database Designer:
Analyzes your logical schema, sample data, and, optionally, your sample queries.
Creates a physical schema design (a set of projections) that can be deployed automatically or manually.
Can be used by anyone without specialized database knowledge.
Can be run and rerun any time for additional optimization without stopping the database.
Uses strategies to provide optimal query performance and data compression.
You can run DBD for just a particular query (optimizes whatever's needed to support that query) or for your entire database. It uses sample queries that you provide, so if your usage patterns change over time it can help to rerun it.

How to start using EF code first migrations on an existing set of databases whilst also using LocalDB for testing

I am working on a system that currently has a number of environments (test, stage, live, etc) each with their own database. So far these databases have been kept in sync by running the same update scripts on each of them.
We are now moving to using EF6 code first migrations, and would also like to start writing some automated system tests using LocalDB.
I've found https://msdn.microsoft.com/pt-pt/data/dn579398 which describes two options for adding an initial migration.
The first method creates an empty initial migration which will work great for the existing environments but won't help with creating LocalDBs for testing.
The second method creates a migration to bring up the whole database from scratch (minus things EF doesn't care about such as sprocs and views). This would be acceptable for testing, but not good for actually recreating a databse. It also requires you to manually comment out the Up method, run the migration on all existing databases, and then put the Up method back. As it will take a while to get the migration through all the environments I'm not keen on this. It also violates the one of the principles of migrations which is that they shouldn't be edited once they've been released.
Having some kind of conditionality in migrations would solve my problem (e.g. if(tableExists("A_table_in_the_existing_database") return;) but there doesn't seem to be anything like that available.
The best I've come up with is to dump the existing database schema from SQL server to a file (which has the advantage of preserving sprocs, views, etc) and then use option 2 above, except instead of using the generated Up method I'll run the SQL file.
However, this still has the drawbacks of option 2 mentioned above, so I'd be very happy to learn of a better way of handling this situation.
Edit:
Would this work? Run the commented out initial migration on one database, then dumping out the __MigrationHistory table and inserting it into the other databases? That way I wouldn't have to wait for the migration to make it through all the environments before I could safely uncomment it.
EF 6.1.2 has support for running SQL embedded as a resource within the assembly containing the migrations using the SqlResource method.
I think I'd go with scripting out your existing schema and using an initial migration that executes SqlResource as its Up. If all it's doing is a bunch of IF EXISTS then it shouldn't take too long to run. Otherwise scripting out __MigrationHistory will also work if you just want to run it once locally and apply to all your other databases by hand.

Why does EF want to create indexes after database restore?

After restoring a database from 1 server to another, I get an AutomaticMigrationsDisabledException from EF saying that the database does match the current model although they actually do match.
So I try to generate a migration from VS and it only contains a bunch of CreateIndex statements for which there already are indexes in the database. And sure enough, when I execute the migration, I get an error.
I previously restored the exact same database to yet another server without any problems. However, the servers are not completely identical. They are all SQL Server 2008, but some have different combinations of SP and KB applied to them.
I'm using EF 6.1.
Can you figure out what the problem is?
It is a bug in version 6.1, will be fixed in 6.1.1 - https://entityframework.codeplex.com/workitem/2167

EF 4 Data Not Refreshing Windows Service

I am running a windows service and it uses EF 4 for its datasource. I use a field as a flag in the database, but when I see the field within the program it is null. I think the issue is that the data must be cached, but at the same time I see the query being run in SQL Profiler (which returns the correct value, not null). Fo course if the data is being cached it makes me wonder why the database is being called at all. So any help would be appreciated.
Wade