mysql < 5.6 has terrible subquery optimization, using EXISTS / JOIN fixes this

This commit is contained in:
Daku 2015-12-04 11:38:44 +00:00
parent 57e5d8e538
commit 6d1c7c414b
2 changed files with 30 additions and 9 deletions

View File

@ -560,9 +560,22 @@ class Image {
*/ */
public function delete_tags_from_image() { public function delete_tags_from_image() {
global $database; global $database;
$database->execute( if($database->get_driver_name() == "mysql") {
"UPDATE tags SET count = count - 1 WHERE id IN ". //mysql < 5.6 has terrible subquery optimization, using EXISTS / JOIN fixes this
"(SELECT tag_id FROM image_tags WHERE image_id = :id)", array("id"=>$this->id)); $database->execute("
UPDATE tags t
INNER JOIN image_tags it ON t.id = it.tag_id
SET count = count - 1
WHERE it.image_id = :id",
array("id"=>$this->id)
);
} else {
$database->execute("
UPDATE tags
SET count = count - 1
WHERE id IN (SELECT tag_id FROM image_tags WHERE image_id = :id)", array("id"=>$this->id)
);
}
$database->execute("DELETE FROM image_tags WHERE image_id=:id", array("id"=>$this->id)); $database->execute("DELETE FROM image_tags WHERE image_id=:id", array("id"=>$this->id));
} }

View File

@ -253,9 +253,9 @@ class Index extends Extension {
$search_terms = $event->get_search_terms(); $search_terms = $event->get_search_terms();
$page_number = $event->get_page_number(); $page_number = $event->get_page_number();
$page_size = $event->get_page_size(); $page_size = $event->get_page_size();
$count_search_terms = count($search_terms); $count_search_terms = count($search_terms);
try { try {
#log_debug("index", "Search for ".implode(" ", $search_terms), false, array("terms"=>$search_terms)); #log_debug("index", "Search for ".implode(" ", $search_terms), false, array("terms"=>$search_terms));
$total_pages = Image::count_pages($search_terms); $total_pages = Image::count_pages($search_terms);
@ -277,7 +277,7 @@ class Index extends Extension {
} }
$count_images = count($images); $count_images = count($images);
if($count_search_terms === 0 && $count_images === 0 && $page_number === 1) { if($count_search_terms === 0 && $count_images === 0 && $page_number === 1) {
$this->theme->display_intro($page); $this->theme->display_intro($page);
send_event(new PostListBuildingEvent($search_terms)); send_event(new PostListBuildingEvent($search_terms));
@ -322,8 +322,17 @@ class Index extends Extension {
// check for tags first as tag based searches are more common. // check for tags first as tag based searches are more common.
if(preg_match("/^tags([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) { if(preg_match("/^tags([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) {
$cmp = ltrim($matches[1], ":") ?: "="; $cmp = ltrim($matches[1], ":") ?: "=";
$tags = $matches[2]; $count = $matches[2];
$event->add_querylet(new Querylet('images.id IN (SELECT DISTINCT image_id FROM image_tags GROUP BY image_id HAVING count(image_id) '.$cmp.' '.$tags.')')); $event->add_querylet(
new Querylet("EXISTS (
SELECT 1
FROM image_tags it
LEFT JOIN tags t ON it.tag_id = t.id
WHERE images.id = it.image_id
GROUP BY image_id
HAVING COUNT(*) $cmp $count
)")
);
} }
else if(preg_match("/^ratio([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+):(\d+)$/i", $event->term, $matches)) { else if(preg_match("/^ratio([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+):(\d+)$/i", $event->term, $matches)) {
$cmp = preg_replace('/^:/', '=', $matches[1]); $cmp = preg_replace('/^:/', '=', $matches[1]);
@ -394,4 +403,3 @@ class Index extends Extension {
$this->stpen++; $this->stpen++;
} }
} }