There's a certain performance issue with the "Ops" field (in Views). I was aware of this from the start, but didn't bother to bring this up.

If you look in 'flag_handler_field_ops.inc' you'll see that its query() method adds a JOIN to the query. The reason is explained in the "Find out if the content is flagged [...]" comment.

And since there's already the main JOIN, we end up with *two* JOINs when the "Ops" field is shown in a view.

The comment I mentioned should be more explicit:

The reason for this extra JOIN is for cases when the flag relationship is added with a "user scope" of "Any user". In this case the "Ops" field handler can't know, just by examining the available columns, whether the item is flagged by the currect user. So it effectively does an extra JOIN with a "user scope" of "Current user".

It's easy to rid of this extra JOIN. This should only be done when the "user scope" of the relationship is "Current user" (and this probably happens in 90% of the cases when we also show the "Ops" field). The query() method should see if its relationship has its 'user_scope' option set to 'current'. If it does, it should skip adding a JOIN and instead have the two aliases ('is_flagged' and 'content_id') point to the columns of the current table.

Comments

mooffie’s picture

A different issue:

It's possible to add yet another performance enhancement to this "Ops" field:

In flag_handler_field_ops::pre_render() we're doing a query to find out which items are flaggable. We can add an "Assume all items are flaggable" checkbox to the Ops configuration form. This will allow the admin to skip this query.

But this is a minor (negligible, probably) preformance issue because this query is a simple one which doesn't affect the [potentially complex] main one.

mitchell’s picture

Component: Code » Flag core

Moving

quicksketch’s picture

mooffie’s picture

Component: Flag core » Views integration
greggles’s picture

crea’s picture

Issue tags: +Perfomance

Subscribing

quicksketch’s picture

Title: The "Ops" performance » Improve performance of the "Ops" field in Views
Version: 6.x-1.x-dev » 7.x-2.x-dev

Updating title for clarity.

q0rban’s picture

Assigned: Unassigned » q0rban

I'm running into an issue with this not mentioned in the first post. If you have multiple flag ops fields on a view, the join happens multiple times. Normally this would never happen, but when you are using something like flag_form, you can actually "edit" a flag, as well as unflag/flag.

q0rban’s picture

Assigned: q0rban » Unassigned
Status: Active » Needs review
StatusFileSize
new3.38 KB

Attached patch fixes both my issue in #8, and bypasses the extra join when the user_scope option is set to "Current User" on the relationship.

IWasBornToWin’s picture

Unless I am doing something wrong I'm not able to apply this patch. Error: Patch cannot be applied to selected content.

joachim’s picture

Status: Needs review » Needs work

Patch applies, but I'm still getting two joins:

FROM 
{node} node
INNER JOIN {flag_content} flag_content_node ON node.nid = flag_content_node.content_id AND (flag_content_node.fid = '1' AND flag_content_node.uid = '1')
LEFT JOIN {users} users_flag_content ON flag_content_node.uid = users_flag_content.uid
LEFT JOIN {flag_content} flag_content ON node.nid = flag_content.content_id AND (flag_content.fid = '1' AND flag_content.uid = '1' AND flag_content.sid = '0')
+++ b/includes/flag_handler_field_ops.inc
@@ -74,27 +74,44 @@ class flag_handler_field_ops extends views_handler_field {
+    if (isset($relationship->options['user_scope']) && $relationship->options['user_scope'] == 'current') {
+      $table_alias = $relationship->alias;
+    }
+    // Otherwise, let's set up the alias, keeping it unique for this flag in
+    // case there are multiple flag relationships in a single view.
+    else {
+      $table_alias = 'flag_content_current_user_' . $flag->fid;
+    }
+    // Now that we have the table alias, let's see if it's already been joined
+    // to. If it hasn't, we'll set up a join.
+    if (!isset($this->query->table_queue[$table_alias])) {

This is the bit I'm suspicious of. Table aliases are tricksy things, and I don't think you can necessarily rely on them like that.

joachim’s picture

Version: 7.x-2.x-dev » 7.x-3.x-dev
joachim’s picture

Status: Needs work » Needs review
StatusFileSize
new2.97 KB

I've looked at this again with a clearer head, and now I get it :) The table alias gets a flag ID appended to it to guarantee uniqueness: 'flag_content_current_user_' . $flag->fid.

Patch looks good, and very well-documented too.

Here's a reroll for the DB changes in 3.x.

joachim’s picture

Status: Needs review » Fixed

Issue #404150 by q0rban: Fixed unnecessary re-adding of table to views showing the 'ops' field with the 'current user' limit on the flag relationship.

joachim’s picture

Version: 7.x-3.x-dev » 7.x-2.x-dev
Status: Fixed » Patch (to be ported)

The patch at #9 should be ok to apply to 2.x -- I don't think I changed anything like comments in my reroll.

IWasBornToWin’s picture

If i install the latest dev do I need to change anything on my end? I have several views joined with flag and want to make sure I can simply upgrade to latest dev.

Thanks

joachim’s picture

I'm not sure what you mean exactly -- and at any rate, please could you post a support request rather than take an issue off-topic?

IWasBornToWin’s picture

Maybe I wasn't clear enough, you said:

The patch at #9 should be ok to apply to 2.x -- I don't think I changed anything like comments in my reroll.

This leads me to believe I can upgrade to avoid the problems of this issue, but I do not want to upgrade if it will cause headaches with all my current views joined to flags.

joachim’s picture

Comment 14 tells you that this issue was fixed on 3.x, because of the way the status was changed.

However, I do not recommend switching production sites to 3.x yet. If you want this fix on 2.x please help test the patch.

  • joachim committed bff5308 on 8.x-4.x
    Issue #404150 by q0rban: Fixed unnecessary re-adding of table to views...
ivnish’s picture

Issue summary: View changes
Status: Patch (to be ported) » Closed (outdated)
Issue tags: -Perfomance

Closed as outdated because Drupal 7 is EOL