Analyze poor MYSQL Query Performance - mysql

I wish to analyze poor MYSQL Query Performance which was happened in different time stamp.
In Oracle, I used to use sqlt (SQLTXPLAIN) report when it's required to analyze poor query performance before and after major version upgrade or executes a query with drastic execution variance in same environment with similar server load. It could provide why SQL is not performing as expected and crucial information (Performance history for the SQL statement, DB parameters, State of CBO stats, Changes on histograms, indexes compare including state, execution plan analysis and all) to actually find root causes before trying to fix performance issue.
Sample Oracle SQLT Report for the reference - http://carlossierradotnet1.files.wordpress.com/2013/04/sqlt_s60032_main.pdf
Can I produce similar report for the MYSQL query which executes with best execution time and worst performance occasionally in the same server environment?
Update:
Capturing long running query and analyze execution plan for a query doesn't work to resolve the problem that I have mentioned in the question. Query doesn't have any problem as it runs without any issue(less than a sec), rarely it behaves with worst performance(hangs sometimes). I am pretty sure, we could pin point the root cause if we get details of Performance history for the SQL statement, State of CBO stats, Changes on histograms, indexes compare including state, execution plan analysis and all for the same query in best and worst timestamp.
I don't have particular query here as it can happen with any complex query if they are running in a big batch, I'd like to provide scenario which might be helpful to understand the problem:
QUERY BATCH#1 - Complex Query#1; Query#2;....Query#10....Complex Query#N;
Situation#1:
All queries are perfectly tuned and runs smoothly when they are executed one by one in a MYSQL prompt.
Situation#2:
QUERY BATCH#1 executing smoothly every night smoothly on 01/05, 02/05, 04/05, 06/05/2014 but Query#2 was taking unacceptable execution time only on 03/05 and Query#10 was taking unacceptable execution time on 05/05/2014. Please be informed that issue was happened with different queries and resource usage (cpu, ram, n/w i/o, storage i/o, etc) and number of db connections are same every day.
Is there any way to check why optimizer took unacceptable time for Query#2 and Query#10 only on 03/05 and 05/05 respectively? Now a days QUERY BATCH#1 runs smoothly every day without applying any changes in the database/system/application.

Related

How to make execution plans as most accurate as possible

every night I make a dump of my PROD environment (mysql 8.0.23) to import it in my TEST environment. The hardware and the mysql config is the same on both systems
I noticed that some query (executed just after the dump, when the 2 databases are still aligned) behave in a different way on the 2 systems, with different execution plans and, of course, different performances
My guess is that the TEST environment performs better because every table is created from scratch, so the stats for tables and indexes are more accurate, while PROD is loaded with tons of inserts, updates, deletes during the day.
Is there any way to make PROD behave the same way?
I tryed to run OPTIMIZE and ANALYZE on every table (most of them are InnoDB), but the execution plans are still different
Thanks
The fresh load on TEST needs to do more I/O because the "cache" is initially empty. (Cf InnoDB's buffer_pool.) I would expect that TEST might be up to 10 times as slow. Run the same query again to see it speed up.
EXPLAIN makes estimates; it is usually inconsistent. Don't worry about that.
If PROD is quite busy, but TEST is just running a single query, PROD could be slower. This is due to the other stuff that is going on.
OPTIMIZE is essentially never needed for InnoDB; don't waste time on it.
ANALYZE will sometimes convince EXPLAIN to provide a different query plan. This does not prove much.
Drop and reimport is unlikely to resolve anything.
Show us one example of a notable difference. We are more likely to spot something when given a specific example. Provide
The query
EXPLAIN SELECT -- on both servers
Timing for the queries
SHOW CREATE TABLE for the table(s) involved in the query.

Mysql Statspack Equivalent

Logging inefficient queries and query frequency in MySQL
We have a pour performing mysql DB. And I'm interested in logging queries and their frequency to assess which ones my time is best spent on. We have slow query logging but these queries aren't the ones hammering the DB. I've been told statspack for Oracle does exactly that with some sort of weighting on the queries.
Any ideas or suggestions would be appreciated.
The MySQL general query log will show all statements being executed. On a busy server, this will grow quickly, and will slow performance, so you likely want to enable it briefly, and then disable it again. That will give you every statement executed, as well as client connects and disconnects.
http://dev.mysql.com/doc/refman/5.5/en/query-log.html
The slow query log can also be a useful tool.
There are some third party tools that can assist with analyzing the output from the general log, the slow query log, and the output from continually running a SHOW FULL PROCESSLIST. One example is MONyog.

MySQL vs SQL Server 2008 R2 simple select query performance

Can anyone explain to me why there is a dramatic difference in performance between MySQL and SQL Server for this simple select statement?
SELECT email from Users WHERE id=1
Currently the database has just one table with 3 users. MySQL time is on average 0.0003 while SQL Server is 0.05. Is this normal or the MSSQL server is not configured properly?
EDIT:
Both tables have the same structure, primary key is set to id, MySQL engine type is InnoDB.
I tried the query with WITH(NOLOCK) but the result is the same.
Are the servers of the same level of power? Hardware makes a difference, too. And are there roughly the same number of people accessing the db at the same time? Are any other applications using the same hardware (databases in general should not share servers with other applications).
Personally I wouldn't worry about this type of difference. If you want to see which is performing better, then add millions of records to the database and then test queries. Database in general all perform well with simple queries on tiny tables, even badly designed or incorrectly set up ones. To know if you will have a performance problem you need to test with large amounts of data and many simulataneous users on hardware similar to the one you will have in prod.
The issue with diagnosing low cost queries is that the fixed cost may swamp the variable costs. Not that I'm a MS-Fanboy, but I'm more familiar with MS-SQL, so I'll address that, primarily.
MS-SQL probably has more overhead for optimization and query parsing, which adds a fixed cost to the query when decising whether to use the index, looking at statistics, etc. MS-SQL also logs a lot of stuff about the query plan when it executes, and stores a lot of data for future optimization that adds overhead
This would all be helpful when the query takes a long time, but when benchmarking a single query, seems to show a slower result.
There are several factors that might affect that benchmark but the most significant is probably the way MySQL caches queries.
When you run a query, MySQL will cache the text of the query and the result. When the same query is issued again it will simply return the result from cache and not actually run the query.
Another important factor is the SQL Server metric is the total elapsed time, not just the time it takes to seek to that record, or pull it from cache. In SQL Server, turning on SET STATISTICS TIME ON will break it down a little bit more but you're still not really comparing like for like.
Finally, I'm not sure what the goal of this benchmarking is since that is an overly simplistic query. Are you comparing the platforms for a new project? What are your criteria for selection?

Mysql query fast only first time run

I have a mysql SELECT query which is fast (<0.1 sec) but only the first time I run it. It joins 3 tables together (using indices) and has a relatively simple WHERE statement. When I run it by hand in the phpmyadmin (always changing numbers in the WHERE so that it isn't cached) it is always fast but when I have php run several copies of it in a row, the first one is fast and the others hang for ~400 sec. My only guess is that somehow mysql is running out of memory for the connection and then has to do expensive paging.
My general question is how can I fix this behavior, but my specific questions are without actually closing and restarting the connection how can I make these queries coming from php be seen as separate just like the queries coming from phpmyadmin, how can I tell mysql to flush any memory when the request is done, and does this sound like a memory issue to you?
Well I found the answer at least in my case and I'm putting it here for anyone in the future who runs into a similar issue. The query I was running had a lot of results returned and MYSQL's query cache was causing a lot of overhead. When you run a query MYSQL will save it and its output so that it can quickly answer future identical requests quickly. All I had to do was put SQL_NO_CACHE and the speed was back to normal. Just look out if your incoming query is large or the results are very large because it can take considerable resources for MYSQL to decide when to kick things out.

MySQL query slowing down until restart

I have a service that sits on top of a MySQL 5.5 database (INNODB). The service has a background job that is supposed to run every week or so. On a high level the background job does the following:
Do some initial DB read and write in one transaction
Execute UMQ (described below) with a set of parameters in one transaction.
If no records are returned we are done!
Process the result from UMQ (this is a bit heavy so it is done outside of any DB
transaction)
Write the outcome of the previous step to DB in one transaction (this
writes to tables queried by UMQ and ensures that the same records are not found again by UMQ).
Goto step 2.
UMQ - Ugly Monster Query: This is a nasty database query that joins a bunch of tables, has conditions on columns in several of these tables and includes a NOT EXISTS subquery with some more joins and conditions. UMQ includes ORDER BY also has LIMIT 1000. Even though the query is bad I have done what I can here - there are indexes on all columns filtered on and the joins are all over foreign key relations.
I do expect UMQ to be heavy and take some time, which is why it's executed in a background job. However, what I'm seeing is rapidly degrading performance until it eventually causes a timeout in my service (maybe 50 times slower after 10 iterations).
First I thought that it was because the data queried by UMQ changes (see step 4 above) but that wasn't it because if I took the last query (the one that caused the timeout) from the slow query log and executed it myself directly I got the same behavior only until I restated the MySQL service. After restart the exact query on the exact same data that took >30 seconds before restart now took <0.5 seconds. I can reproduce this behavior every time by restoring the database to it's initial state and restarting the process.
Also, using the trick described in this question I could see that the query scans around 60K rows after restart as opposed to 18M rows before. EXPLAIN tells me that around 10K rows should be scanned and the result of EXPLAIN is always the same. No other processes are accessing the database at the same time and the lock_time in the slow query log is always 0. SHOW ENGINE INNODB STATUS before and after restart gives me no hints.
So finally the question: Does anybody have any clue of why I'm seeing this behavior? And how can I analyze this further?
I have the feeling that I need to configure MySQL differently in some way but I have searched and tested like crazy without coming up with anything that makes a difference.
Turns out that the behavior I saw was the result of how the MySQL optimizer uses InnoDB statistics to decide on an execution plan. This article put me on the right track (even though it does not exactly discuss my problem). The most important thing I learned from this is that MySQL calculates statistics on startup and then once in a while. This statistics is then used to optimize queries.
The way I had set up the test data the table T where most writes are done in step 4 started out as empty. After each iteration T would contain more and more records but the InnoDB statistics had not yet been updated to reflect this. Because of this the MySQL optimizer always chose an execution plan for UMQ (which includes a JOIN with T) that worked well when T was empty but worse and worse the more records T contained.
To verify this I added an ANALYZE TABLE T; before every execution of UMQ and the rapid degradation disappeared. No lightning performance but acceptable. I also saw that leaving the database for half an hour or so (maybe a bit shorter but at least more than a couple of minutes) would allow the InnoDB statistics to refresh automatically.
In a real scenario the relative difference in index cardinality for the tables involved in UMQ will look quite different and will not change as rapidly so I have decided that I don't really need to do anything about it.
thank you very much for the analysis and answer. I've been searching this issue for several days during ci on mariadb 10.1 and bacula server 9.4 (debian buster).
The situation was that after fresh server installation during a CI cycle, the first two tests (backup and restore) runs smoothly on unrestarted mariadb server and only the third test showed that one particular UMQ took about 20 minutes (building directory tree during restore process from the table with about 30k rows).
Unless the mardiadb server was restarted or table has been analyzed the problem would not go away. ANALYZE TABLE or the restart changed the cardinality of the fields and internal query processing exactly as stated in the linked article.