From 52053f355af6c09db547f1b8d02bb9ae88abcb1c Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Sat, 13 Feb 2016 11:33:01 +0100 Subject: [PATCH] Performance: Optimize kolab_storage_folder::get_object() to use one sql query instead of two Before the change to get an object by UID we first resolve UID to IMAP-UID and then fetch the object data by IMAP-UID - two select queries. Now we directly select the data by UID. --- plugins/libkolab/lib/kolab_storage_cache.php | 7 +++- plugins/libkolab/lib/kolab_storage_folder.php | 33 ++++++++++++++++--- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/plugins/libkolab/lib/kolab_storage_cache.php b/plugins/libkolab/lib/kolab_storage_cache.php index 162c220d..800195a8 100644 --- a/plugins/libkolab/lib/kolab_storage_cache.php +++ b/plugins/libkolab/lib/kolab_storage_cache.php @@ -665,7 +665,12 @@ class kolab_storage_cache public function set_order_by($sortcols) { if (!empty($sortcols)) { - $this->order_by = '`' . join('`, `', (array)$sortcols) . '`'; + $sortcols = array_map(function($v) { + list($column, $order) = explode(' ', $v, 2); + return "`$column`" . ($order ? " $order" : ''); + }, (array) $sortcols); + + $this->order_by = join(', ', $sortcols); } else { $this->order_by = null; diff --git a/plugins/libkolab/lib/kolab_storage_folder.php b/plugins/libkolab/lib/kolab_storage_folder.php index 44fe6956..99ea7297 100644 --- a/plugins/libkolab/lib/kolab_storage_folder.php +++ b/plugins/libkolab/lib/kolab_storage_folder.php @@ -348,6 +348,12 @@ class kolab_storage_folder extends kolab_storage_folder_api if ($length !== null) { $this->cache->set_limit($length, $offset); } + + $this->order_and_limit = array( + 'cols' => $sortcols, + 'limit' => $length, + 'offset' => $offset, + ); } /** @@ -376,7 +382,6 @@ class kolab_storage_folder extends kolab_storage_folder_api return $query; } - /** * Getter for a single Kolab object, identified by its UID * @@ -388,17 +393,35 @@ class kolab_storage_folder extends kolab_storage_folder_api */ public function get_object($uid, $type = null) { - if (!$this->valid) { + if (!$this->valid || !$uid) { return false; } + $query = array(array('uid', '=', $uid)); + + if ($type) { + $query[] = array('type', '=', $type); + } + // synchronize caches $this->cache->synchronize(); - $msguid = $this->cache->uid2msguid($uid); + // we don't use cache->get() here because we don't have msguid + // yet, using select() is faster - if ($msguid && ($object = $this->cache->get($msguid, $type))) { - return $object; + // set order to make sure we get most recent object version + // set limit to skip count query + $this->cache->set_order_by('msguid DESC'); + $this->cache->set_limit(1); + + $list = $this->cache->select($this->_prepare_query($query)); + + // set the order/limit back to defined value + $this->cache->set_order_by($this->order_and_limit['order']); + $this->cache->set_limit($this->order_and_limit['limit'], $this->order_and_limit['offset']); + + if (!empty($list) && !empty($list[0])) { + return $list[0]; } return false;