I am running several thousand python processes on multiple servers which go off, lookup a website, do some analysis and then write the results to a central MySQL database.
It all works fine for about 8 hours and then my scripts start to wait for a MySQL connection.
On checking top it's clear that the MySQL daemon is overloaded as it is using up to 90% of most of the CPUs.
When I stop all my scripts, MySQL continues to use resources for some time afterwards.
I assume it is still updating the indexes? - If so, is there anyway of determining which indexes it is working on, or if not what it is actually doing?
Many thanks in advance.
Try enabling the slow query log: http://dev.mysql.com/doc/refman/5.1/en/slow-query-log.html
Also, take a look at the output of SHOW PROCESSLIST; on the mysql shell, it should give you some more information.
There are a lot of tweaks that can be done to improve the performance of MySQL. Given your workload, you would probably benefit a lot from mysql 5.5 and higher, which improved performance on multiprocessor machines. Is the machine in question hitting VM? if it is paging out, then the performance of mysql will be horrible.
My suggestions:
check version of mysql. If possible, get the latest 5.5 version.
Look at the config files for mysql called my.cnf. Make sure that it makes sense on your machine. There are example config files for small, medium, large, etc machines to run MySQL. I think the default setup is for a machine with < 1 Gig of ram.
As the other answer suggests, turn on slow query logging.
Related
I have deployed a webapplication Python Django Rest Framework Front end is Vue js and Database is Mysql.
Hosted the website on digital ocean i am using CPU Optimized Droplets with the below configuration 8 GB 4 vCPUs i facing performance issue the site is very slow though the hosting is CPU optimized with 8gb of ram.
When i checked the error log i am able to find [CRITICAL] WORKER TIMEOUT (pid:9116) i increased the timeout time of the gunicorn still i am facing the same issue.
1)I want to increase the performance
2)I want to fix the timeout issue i have increased the value in gunicorn as nginx the maximum value is 75s i have not done any addition to it. what will be th best solution.
Kindly help me is there any alternative ways to test the performance of the site.
I think you need optimization
Tips on optimizing your django rest on production server .
Check your queries. Best way to check this is using the django debug toolbar, it will show how many queries you produce and if you think there is a lot, then optimize your queries. Ex. use prefetch_related or select_related to join the tables or else it will query one by one.
Index your tables, try to index the columns you're always using on querying. Just be careful on indexing, just index the columns you really wanted because the downside will be slower on update, delete and add.
Check your database health, if you perform delete or update frequently those data actually stored somewhere and it is still part of your indexes, it called Dead Rows, you can remove this by perform some commands like vacuum if your are using postgres.
Scale up your server, this actually depends on the request/traffic of your server, check the RAM or CPU spikes for you to determine the needed units. As experience, I have atleast 10m row of data on some of my tables, which in some scenario I cross refer it to a 30k data, on 2gb RAM and 1gb CPU working fine in few simultaneous request.
I face the problem of an extremely slow (raw) query in my Django app. Strangely enough, it's not slow when I launch the isolated query from the shell (ex: python manage.py my_code_query) but it's slow when I run the whole program that contains all my querys (it "blocks" always at the same query; actually it eventually completes but it's something like 100x slower). It's like if all the queries that are before the problematic one are consuming memory and there is not enough memory left when my query starts. The query ran directly from Postgres has no problem at all.
I read somewhere (Django cursor.execute(QUERY) much slower than running the query in the postgres database) that it can be the work_mem setting in Postgres that causes the problem but they are not very clear about the way they set it from Django. Do I have to make a call from my connection.cursor.execute() to set the work_mem parameter? Once only?
Could it be another problem than the work_mem setting?
Any hint will be very appreciated.
Thanks,
Patrick
Inspired by that post (How can I tell Django to execute all queries using 10MB statement mem?), I made this call before executing my cursor:
cursor.execute("set work_mem='100MB'") #set statement_mem does not work
It's running timely now.
--EDIT: Well, that was yesterday. Today it's not running timely anymore. Don't know why.
I'm tinkering with some big-data queries in the ipython shell using the Django ORM. This is on a Debian 6 VM in VMware Fusion on OS X, the VM is allowed access 4 or 8 cores (I've played with the settings) of the 4-core HT i7 on the host.
When I watch the progress in top, when doing for example a 'for result in results: do_query()' in the python shell, it seems that python and one of the postgres processes are always co-located on the same physical CPU core - their total CPU usage never adds up to more than 100%, python is usually 65% to postgres' 25% or so. iowait on the VM isn't excessively high.
I'm not positive they're always on the same core, but it sure looks it. Given how I plan to scale this eventually, I'd prefer that the python process(es) and postgress workers be scheduled more optimally. Any insight?
Right now, if your code works the way I think it works, Postgres is always waiting for Python to send it a query, or Python is waiting for Postgres to come back with a response. There's no situation where they'd both be doing work at once, so only one ever runs at a time.
To start using your machine more heavily, you'll need to implement some sort of multithreading on the Python end. Since you haven't given many details on what your queries are, it's hard to say what that might look like.
I'm writing a Oracle of Bacon type website that involves a breadth first search on a very large directed graph (>5 million nodes with an average of perhaps 30 outbound edges each). This is also essentially all the site will do, aside from display a few mostly text pages (how it works, contact info, etc.). I currently have a test implementation running in Python, but even using Python arrays to efficiently represent the data, it takes >1.5gb of RAM to hold the whole thing. Clearly Python is the wrong language for a low-level algorithmic problem like this, so I plan to rewrite most of it in C using the Python/C bindings. I estimate that this'll take about 300 mb of RAM.
Based on my current configuration, this will run through mod_wsgi in apache 2.2.14, which is set to use mpm_worker_module. Each child apache server will then load up the whole python setup (which loads the C extension) thus using 300 mb, and I only have 4gb of RAM. This'll take time to load and it seems like it'd potentially keep the number of server instances lower than it could otherwise be. If I understand correctly, data-heavy (and not client-interaction-heavy) tasks like this would typically get divorced from the server by setting up an SQL database or something of the sort that all the server processes could then query. But I don't know of a database framework that'd fit my needs.
So, how to proceed? Is it worth trying to set up a database divorced from the webserver, or in some other way move the application a step farther out than mod_wsgi, in order to maybe get a few more server instances running? If so, how could this be done?
My first impression is that the database, and not the server, is always going to be the limiting factor. It looks like the typical Apache mpm_worker_module configuration has ServerLimit 16 anyways, so I'd probably only get a few more servers. And if I did divorce the database from the server I'd have to have some way to run multiple instances of the database as well (I already know that just one probably won't cut it for the traffic levels I want to support) and make them play nice with the server. So I've perhaps mostly answered my own question, but this is a kind of odd situation so I figured it'd be worth seeing if anyone's got a firmer handle on it. Anything I'm missing? Does this implementation make sense? Thanks in advance!
Technical details: it's a Django website that I'm going to serve using Apache 2.2.14 on Ubuntu 10.4.
First up, look at daemon mode of mod_wsgi and don't use embedded mode as then you can control separate to Apache child processes the number of Python WSGI application processes. Secondly, you would be better off putting the memory hungry bits in a separate backend process. You might use XML-RPC or other message queueing system to communicate with the backend processes, or even perhaps see if you can use Celery in some way.
I have a script with a main for loop that repeats about 15k times. In this loop it queries a local MySQL database and does a SVN update on a local repository. I placed the SVN repository in a RAMdisk as before most of the time seemed to be spent reading/writing to disk.
Now I have a script that runs at basically the same speed but CPU utilization for that script never goes over 10%.
ProcessExplorer shows that mysqld is also not taking almost any CPU time or reading/writing a lot to disk.
What steps would you take to figure out where the bottleneck is?
Doing SQL queries in a for loop 15k times is a bottleneck in every language..
Is there any reason you query every time again ? If you do a single query before the for loop and then loop over the resultset and the SVN part, you will see a dramatic increase in speed.
But I doubt that you will get a higher CPU usage. The reason is that you are not doing calculations, but mostly IO.
Btw, you can't measure that in mysqld cpu usage, as it's in the actual code not complexity of the queries, but their count and the latency of the server engine to answer. So you will see only very short, not expensive queries, that do sum up in time, though.
Profile your Python code. That will show you how long each function/method call takes. If that's the method call querying the MySQL database, you'll have a clue where to look. But it also may be something else. In any case, profiling is the usual approach to solve such problems.
It is "well known", so to speak, that svn update waits up to a whole second after it has finished running, so that file modification timestamps get "in the past" (since many filesystems don't have a timestamp granularity finer than one second). You can find more information about it by Googling for "svn sleep_for_timestamps".
I don't have any obvious solution to suggest. If this is really performance critical you could either: 1) not update as often as you are doing 2) try to use a lower-level Subversion API (good luck).