Drupal devel module displays the SQL execution time in cache, not on the SQL server.
Example taken from my website (500.000 posts), opening a forum thread:
SELECT n.nid, n.title, n.sticky, l.comment_count, l.last_comment_timestamp FROM node n INNER JOIN node_comment_statistics l ON n.nid = l.nid INNER JOIN term_node r ON n.nid = r.nid AND r.tid = 9 WHERE n.status = 1 ORDER BY n.sticky DESC, l.last_comment_timestamp DESC
371ms
You can believe it is a lot ...
In fact, you should always check execution time in a graphical SQL client like pgAdmin3:
SELECT n.nid, n.title, n.sticky, l.comment_count, l.last_comment_timestamp FROM node n INNER JOIN node_comment_statistics l ON n.nid = l.nid INNER JOIN term_node r ON n.nid = r.nid AND r.tid = 9 WHERE n.status = 1 ORDER BY n.sticky DESC, l.last_comment_timestamp DESC
This query returns 21000 rows in 7412 ms.
You cache is propably full, your memory is eaten-up and your CPU time is lost.
If 100 people connect to the forum, even with cache and a good PostgreSQL server (don't even think of MySQL), it will be down in 2 minutes. People can also attack a forum quite easily.
So ... We need to fix this in code. We don't need 21000 rows for a single thread.
I will propose a fix ASAP.
Comment | File | Size | Author |
---|---|---|---|
#22 | vacances-011.png | 197.41 KB | azertya123 |
Comments
Comment #1
grub3 CreditAttribution: grub3 commentedThe problem comes from this part of code:
db_fetch_object($result) should not be used to fetch and analyse 21.000 records.
I cannot fix this PHP function and leave this to core developers.
Comment #2
grub3 CreditAttribution: grub3 commentedSetting to critical as no serious forum can work with kind of query.
Comment #3
Damien Tournoud CreditAttribution: Damien Tournoud commentedJean-Michel, this is a friendly warning, please change your behavior. This is getting really annoying.
Comment #4
grub3 CreditAttribution: grub3 commentedSorry, I apologize.
I modified all recent messages to correct them.
This message is part of a tutorial which I am writing here:
Guidelines for writing efficient SQL code
Kind regards,
Jean-Michel
Comment #5
grub3 CreditAttribution: grub3 commentedCan you modify the title of this message to:
"Drupal query returns 21000 rows, which are computed using PHP"
Why cannot-it be fixed?
Is this a no-op for you?
Comment #6
Scott Reynolds CreditAttribution: Scott Reynolds commentedgood news its in a theme function and you can override it: http://drupal.org/node/55126
What this query is doing of course is finding the next and previous. For an outstanding discussion on the problems of finding next and previous: http://2bits.com/articles/previousnext-api-high-performance-api-module-p...
And: http://www.slideshare.net/Eweaver/efficient-pagination-using-mysql
Comment #7
grub3 CreditAttribution: grub3 commentedReally thank you, I am relieved.
I will transfer bug to the theme maintainer.
Comment #8
grub3 CreditAttribution: grub3 commentedDo you think it can be used:
http://drupal.org/project/prev_next
Comment #9
grub3 CreditAttribution: grub3 commentedThe bug was closed by Damien and handed to the theme developers by myself. I hope that D7 offers such a feature, integrated. It not normal to query 21.000 rows just for the sole display of Previous/Next and compute them in PHP one by one.
Now I have to download http://drupal.org/project/prev_next and modify Drupal core. I am getting lost.
I have to admit strange things are going on in Drupal and don't blame me. I am not a troll: I participated in pgAdmin3 development, kdenlive video editor. I optimized several PHPBB SQL queries for scalibility and I am quite amazed by the low-level of attention to this previous/next link. And more over to database performance. I did my best and spent a couple of days reviewing Drupal problems under PostgreSQL and wrote two guides: http://drupal.org/node/559302 and http://drupal.org/node/555514.
Previous/next is one the bases of the web. Many people concentrate on cache here, people discuss about farms, but is it really needed if a framework cannot scale Prev/Next to 650.000 records. There are SQL design problems to handle quickly. Again, I hope this is fixed in D7.
My website is going live in a few days. If I publish it with Drupal current internals, it may explode. Now I am prepared for anything. Of course, I will disable prev/next link.
Can we discuss what could be done for Prev/Next navigation to get it into core Drupal 6-dev forum. Or is this impossible by nature of Drupal coding?
I would like to escalate directly to Dries Buytaert and pledge him to ask the community to fix this prev/next problem, quickly. Several sites may be suffering from heavy load problems. If admins do not have access to MySQL or PostgreSQL settings, they may not be able to log queries server-side and thus will never discover this simple pagination problem.
This is the problem of using tools like MySQL. You never really know what is going on. People are discussing about caching MySQL, but Previous/Next is not fixed in the drupal forum. I can only encourage your teams to read my two guides and migrate to PostgreSQL. Today, drupal.org became very slow. Why not migrate to PostgreSQL and log all slow query plans. This would allow you to optimize Drupal quickly. This is not a joke, I really believe it. If you are interested, I can help.
Dries, please, help, what is your opinion? Can you get scalable Prev/Next links in Drupal forum? With not provide a scalable API for Prev/Next within Drupal. Are there reason?
Kind regards,
Jean-Michel
Comment #10
grub3 CreditAttribution: grub3 commentedFinally, I decided to reopen this bug and escalate to Dries directly.
Damien, I still don't believe why you closed that bug.
This is a heavy problem in forum and closing the bug will not remove problems.
Comment #11
Dave ReidHoly crap jmpoure, this is not how the community works. We don't beg to Dries.
Comment #12
grub3 CreditAttribution: grub3 commentedThanks, I got confirmation from the dev list that this issue would be studied and probably fixed. Thank you very much Drupalers.
Comment #13
philipnet CreditAttribution: philipnet commentedJean-Michel,
Do you have any suggestions of a better way to write the SQL so that we don't have PHP iterating through potentially tens of thousands of records just to print Previous and Next links?
Can we just select the n.nid we need and then ask the RDMS for the previous and next nids?
* I think only MySQL supports 'previous_record' and 'next_record' functions?
* Do PostgreSQL and SQLite also offer those functions?
Do we need to bring {node_comment_statistics} in?
A quick Google has revealed this thread on the MySQL site: http://forums.mysql.com/read.php?52,221129
Does that scale better?
Does it work with PostgreSQL and SQLite?
Any other ideas?
Comment #14
grub3 CreditAttribution: grub3 commentedPardon me, but I am very new to Drupal API to I might write nonsence.
Presently I am working like hell to verify SQL scalibility reading server-side queries.
For previous, current and next record, why not use a SQL combination of LIMIT and OFFSET?
This makes it possible to fetch only three records:
SELECT select_list
FROM table_expression
[ ORDER BY ... ]
LIMIT 3 OFFSET n-1
Where n is the record that you would like.
http://www.postgresql.org/docs/8.4/interactive/queries-limit.html
Again, I don't know how to handle that in Drupal, but it ***seems*** to make sense to use LIMIT OFFSET
Usually the database is able to use indexes and access data directly, thus it can be lightning fast with no overhead.
We can always check the detailed plans.
But it seems more reasonable to run 100 queries with LIMIT OFFSET and store results in cache
rather than sending ONE huge SQL Query to the database.
LIMIT OFFSET scales to all databases.
Generally, it is more interesting to run a collection of queries returning 1 to 10 records max that running 1 huge SQL query and storing it in cache for later PHP processing. Processing 21.000 records in PHP demands too much PHP memory. This can drive performance down.
Running multiple short SQL queries returning 1 to 10 records scales better.
In the case of LIMIT 3 OFFSET n-1 it is pretty obvious.
What is your opinion?
Comment #15
grub3 CreditAttribution: grub3 commentedFor example, I run this arbitrary query fetching 3 records out of 21.000 thousands in 266 ms:
This seems very slow.
Let us add an index:
Now, the query plan is:
This query can execute in 168ms
Notice a cast from int_unsigned to int happens.
This should not be the case and I contacted PostgreSQL hackers for that problem.
Because of ORDER BY, we cannot avoid a sequential scan or a sort in memory.
i believe that this query should run more quickly when the CAST problem is fixed.
PostgreSQL hackers believe that this is a problem with my install.
Comment #16
ngaur CreditAttribution: ngaur commentedThanks for your effort and persistence jmpoure.
Comment #21
johnny guimauve CreditAttribution: johnny guimauve commentedSorry for my english I post also from France and like jmpoure this is not my natural language.
I would like to say thank you to jmpoure for all the advices and the bug repair he do for us drupal users.
I had to migrate a very big forum to drupal soon and the capacity of jean michel poure to do this thing is very a lot of help in the french informatician communauty, let me tell you he is a very good help because he translate all the advices and patches into is forum which is read by 650.000 persons every week, and a lot of informaticians here are teached by him.
Thanx jm, god bless you
Comment #22
azertya123 CreditAttribution: azertya123 commentedThank you for your effort to became a great developper. Is it your first experience with Drupal ? I think you are the best to floute very beautiful houses.
For example this one :
Comment #23
Dave ReidWell this was interesting thread to read via e-mail subscriptions.
Comment #24
Jody LynnFYI this function was removed from D7: #556136: Remove theme_forum_topic_navigation()
Comment #25
Damien Tournoud CreditAttribution: Damien Tournoud commentedThen it's won't fix. This query is a known performance problem, but nothing we can fix in a stable version of Drupal.