diff --git a/apps/files_trashbin/lib/BackgroundJob/ExpireTrash.php b/apps/files_trashbin/lib/BackgroundJob/ExpireTrash.php
index 7d481afeb59d75a1337b78b0929a2adf4617b57d..d366a401e2f54e4aa164894fa8ffd67e13934e93 100644
--- a/apps/files_trashbin/lib/BackgroundJob/ExpireTrash.php
+++ b/apps/files_trashbin/lib/BackgroundJob/ExpireTrash.php
@@ -77,9 +77,9 @@ class ExpireTrash extends \OC\BackgroundJob\TimedJob {
 			return;
 		}
 
-		$this->userManager->callForAllUsers(function(IUser $user) {
+		$this->userManager->callForSeenUsers(function(IUser $user) {
 			$uid = $user->getUID();
-			if ($user->getLastLogin() === 0 || !$this->setupFS($uid)) {
+			if (!$this->setupFS($uid)) {
 				return;
 			}
 			$dirContent = Helper::getTrashFiles('/', $uid, 'mtime');
diff --git a/apps/files_trashbin/lib/Command/ExpireTrash.php b/apps/files_trashbin/lib/Command/ExpireTrash.php
index ff8277188850c528f77b3c175675a4e91785b209..b016fdd6aeb1a766dcea0a849465bedb919b2c56 100644
--- a/apps/files_trashbin/lib/Command/ExpireTrash.php
+++ b/apps/files_trashbin/lib/Command/ExpireTrash.php
@@ -89,7 +89,7 @@ class ExpireTrash extends Command {
 		} else {
 			$p = new ProgressBar($output);
 			$p->start();
-			$this->userManager->callForAllUsers(function(IUser $user) use ($p) {
+			$this->userManager->callForSeenUsers(function(IUser $user) use ($p) {
 				$p->advance();
 				$this->expireTrashForUser($user);
 			});
@@ -100,7 +100,7 @@ class ExpireTrash extends Command {
 
 	function expireTrashForUser(IUser $user) {
 		$uid = $user->getUID();
-		if ($user->getLastLogin() === 0 || !$this->setupFS($uid)) {
+		if (!$this->setupFS($uid)) {
 			return;
 		}
 		$dirContent = Helper::getTrashFiles('/', $uid, 'mtime');
diff --git a/apps/files_versions/lib/BackgroundJob/ExpireVersions.php b/apps/files_versions/lib/BackgroundJob/ExpireVersions.php
index 8e1f02cdfbf0c0a6ec3e42438949cb35b0163d70..89b8a9661371231fbc196bb98fbe331009419d11 100644
--- a/apps/files_versions/lib/BackgroundJob/ExpireVersions.php
+++ b/apps/files_versions/lib/BackgroundJob/ExpireVersions.php
@@ -67,9 +67,9 @@ class ExpireVersions extends \OC\BackgroundJob\TimedJob {
 			return;
 		}
 
-		$this->userManager->callForAllUsers(function(IUser $user) {
+		$this->userManager->callForSeenUsers(function(IUser $user) {
 			$uid = $user->getUID();
-			if ($user->getLastLogin() === 0 || !$this->setupFS($uid)) {
+			if (!$this->setupFS($uid)) {
 				return;
 			}
 			Storage::expireOlderThanMaxForUser($uid);
diff --git a/apps/files_versions/lib/Command/ExpireVersions.php b/apps/files_versions/lib/Command/ExpireVersions.php
index f384420f22f71095ab6f10b3ed8de6422b205630..e88ea1f7a0270b01400cbb173a2ff26914cce5e3 100644
--- a/apps/files_versions/lib/Command/ExpireVersions.php
+++ b/apps/files_versions/lib/Command/ExpireVersions.php
@@ -88,7 +88,7 @@ class ExpireVersions extends Command {
 		} else {
 			$p = new ProgressBar($output);
 			$p->start();
-			$this->userManager->callForAllUsers(function(IUser $user) use ($p) {
+			$this->userManager->callForSeenUsers(function(IUser $user) use ($p) {
 				$p->advance();
 				$this->expireVersionsForUser($user);
 			});
@@ -99,7 +99,7 @@ class ExpireVersions extends Command {
 
 	function expireVersionsForUser(IUser $user) {
 		$uid = $user->getUID();
-		if ($user->getLastLogin() === 0 || !$this->setupFS($uid)) {
+		if (!$this->setupFS($uid)) {
 			return;
 		}
 		Storage::expireOlderThanMaxForUser($uid);
diff --git a/lib/private/Repair/RemoveRootShares.php b/lib/private/Repair/RemoveRootShares.php
index 1fd7d8d7dae9ee29c9e67a295a4ccaa88db9a81a..69fcb1b44925851ca04b5a3a133a46c6bf43ce68 100644
--- a/lib/private/Repair/RemoveRootShares.php
+++ b/lib/private/Repair/RemoveRootShares.php
@@ -96,30 +96,13 @@ class RemoveRootShares implements IRepairStep {
 			$output->advance();
 		};
 
-		$userCount = $this->countUsers();
-		$output->startProgress($userCount);
+		$output->startProgress($this->userManager->countSeenUsers());
 
-		$this->userManager->callForAllUsers($function);
+		$this->userManager->callForSeenUsers($function);
 
 		$output->finishProgress();
 	}
 
-	/**
-	 * Count all the users
-	 *
-	 * @return int
-	 */
-	private function countUsers() {
-		$allCount = $this->userManager->countUsers();
-
-		$totalCount = 0;
-		foreach ($allCount as $backend => $count) {
-			$totalCount += $count;
-		}
-
-		return $totalCount;
-	}
-
 	/**
 	 * Verify if this repair steps is required
 	 * It *should* not be necessary in most cases and it can be very
diff --git a/lib/private/Repair/RepairUnmergedShares.php b/lib/private/Repair/RepairUnmergedShares.php
index d57bc3779f859c89363c5505f5bbdda0ebfe675d..56d935c74f56b1be1a2bd0756f6f06d140580919 100644
--- a/lib/private/Repair/RepairUnmergedShares.php
+++ b/lib/private/Repair/RepairUnmergedShares.php
@@ -335,22 +335,6 @@ class RepairUnmergedShares implements IRepairStep {
 		}
 	}
 
-	/**
-	 * Count all the users
-	 *
-	 * @return int
-	 */
-	private function countUsers() {
-		$allCount = $this->userManager->countUsers();
-
-		$totalCount = 0;
-		foreach ($allCount as $backend => $count) {
-			$totalCount += $count;
-		}
-
-		return $totalCount;
-	}
-
 	public function run(IOutput $output) {
 		$ocVersionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0');
 		if (version_compare($ocVersionFromBeforeUpdate, '9.1.0.16', '<')) {
@@ -363,8 +347,7 @@ class RepairUnmergedShares implements IRepairStep {
 
 			$this->buildPreparedQueries();
 
-			$userCount = $this->countUsers();
-			$output->startProgress($userCount);
+			$output->startProgress($this->userManager->countUsers());
 
 			$this->userManager->callForAllUsers($function);
 
diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php
index 7d8c6d48b2c67797e7a15918ab93910333e87ba2..f048863748578dfdf5e70ac0ca613e6ee83d3676 100644
--- a/lib/private/User/Manager.php
+++ b/lib/private/User/Manager.php
@@ -314,10 +314,16 @@ class Manager extends PublicEmitter implements IUserManager {
 	/**
 	 * returns how many users per backend exist (if supported by backend)
 	 *
-	 * @return array an array of backend class as key and count number as value
+	 * @param boolean $hasLoggedIn when true only users that have a lastLogin
+	 *                entry in the preferences table will be affected
+	 * @return array|int an array of backend class as key and count number as value
+	 *                if $hasLoggedIn is true only an int is returned
 	 */
-	public function countUsers() {
-		$userCountStatistics = array();
+	public function countUsers($hasLoggedIn = false) {
+		if ($hasLoggedIn) {
+			return $this->countSeenUsers();
+		}
+		$userCountStatistics = [];
 		foreach ($this->backends as $backend) {
 			if ($backend->implementsActions(Backend::COUNT_USERS)) {
 				$backendUsers = $backend->countUsers();
@@ -344,29 +350,120 @@ class Manager extends PublicEmitter implements IUserManager {
 	 *
 	 * @param \Closure $callback
 	 * @param string $search
+	 * @param boolean $onlySeen when true only users that have a lastLogin entry
+	 *                in the preferences table will be affected
 	 * @since 9.0.0
 	 */
-	public function callForAllUsers(\Closure $callback, $search = '') {
-		foreach($this->getBackends() as $backend) {
-			$limit = 500;
-			$offset = 0;
-			do {
-				$users = $backend->getUsers($search, $limit, $offset);
-				foreach ($users as $uid) {
-					if (!$backend->userExists($uid)) {
-						continue;
+	public function callForAllUsers(\Closure $callback, $search = '', $onlySeen = false) {
+		if ($onlySeen) {
+			$this->callForSeenUsers($callback);
+		} else {
+			foreach ($this->getBackends() as $backend) {
+				$limit = 500;
+				$offset = 0;
+				do {
+					$users = $backend->getUsers($search, $limit, $offset);
+					foreach ($users as $uid) {
+						if (!$backend->userExists($uid)) {
+							continue;
+						}
+						$user = $this->getUserObject($uid, $backend, false);
+						$return = $callback($user);
+						if ($return === false) {
+							break;
+						}
 					}
-					$user = $this->getUserObject($uid, $backend, false);
-					$return = $callback($user);
-					if ($return === false) {
-						break;
+					$offset += $limit;
+				} while (count($users) >= $limit);
+			}
+		}
+	}
+
+	/**
+	 * returns how many users have logged in once
+	 *
+	 * @return int
+	 * @since 9.2.0
+	 */
+	public function countSeenUsers() {
+		$queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
+		$queryBuilder->select($queryBuilder->createFunction('COUNT(*)'))
+			->from('preferences')
+			->where($queryBuilder->expr()->eq(
+				'appid', $queryBuilder->createNamedParameter('login'))
+			)
+			->andWhere($queryBuilder->expr()->eq(
+				'configkey', $queryBuilder->createNamedParameter('lastLogin'))
+			)
+			->andWhere($queryBuilder->expr()->isNotNull('configvalue')
+			);
+
+		$query = $queryBuilder->execute();
+		return (int)$query->fetchColumn();
+	}
+
+	/**
+	 * @param \Closure $callback
+	 * @param string $search
+	 * @since 9.2.0
+	 */
+	public function callForSeenUsers (\Closure $callback) {
+		$limit = 1000;
+		$offset = 0;
+		do {
+			$userIds = $this->getSeenUserIds($limit, $offset);
+			$offset += $limit;
+			foreach ($userIds as $userId) {
+				foreach ($this->backends as $backend) {
+					if ($backend->userExists($userId)) {
+						$user = $this->getUserObject($userId, $backend, false);
+						$return = $callback($user);
+						if ($return === false) {
+							return;
+						}
 					}
 				}
-				$offset += $limit;
-			} while (count($users) >= $limit);
-		}
+			}
+		} while (count($userIds) >= $limit);
 	}
 
+	/**
+	 * Getting all userIds that have a listLogin value requires checking the
+	 * value in php because on oracle you cannot use a clob in a where clause,
+	 * preventing us from doing a not null or length(value) > 0 check.
+	 * 
+	 * @param int $limit
+	 * @param int $offset
+	 * @return string[] with user ids
+	 */
+	private function getSeenUserIds($limit = null, $offset = null) {
+		$queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
+		$queryBuilder->select(['userid'])
+			->from('preferences')
+			->where($queryBuilder->expr()->eq(
+				'appid', $queryBuilder->createNamedParameter('login'))
+			)
+			->andWhere($queryBuilder->expr()->eq(
+				'configkey', $queryBuilder->createNamedParameter('lastLogin'))
+			)
+			->andWhere($queryBuilder->expr()->isNotNull('configvalue')
+			);
+
+		if ($limit !== null) {
+			$queryBuilder->setMaxResults($limit);
+		}
+		if ($offset !== null) {
+			$queryBuilder->setFirstResult($offset);
+		}
+		$query = $queryBuilder->execute();
+		$result = [];
+
+		while ($row = $query->fetch()) {
+			$result[] = $row['userid'];
+		}
+
+		return $result;
+	}
 	/**
 	 * @param string $email
 	 * @return IUser[]
diff --git a/lib/public/IUserManager.php b/lib/public/IUserManager.php
index 1e0c298edcfbb602bce20c1d839e6586c68de9bb..854622335c83f6044190198fa631da0f1aeb6ead 100644
--- a/lib/public/IUserManager.php
+++ b/lib/public/IUserManager.php
@@ -144,6 +144,21 @@ interface IUserManager {
 	 */
 	public function callForAllUsers (\Closure $callback, $search = '');
 
+	/**
+	 * returns how many users have logged in once
+	 *
+	 * @return int
+	 * @since 9.2.0
+	 */
+	public function countSeenUsers();
+
+	/**
+	 * @param \Closure $callback
+	 * @param string $search
+	 * @since 9.2.0
+	 */
+	public function callForSeenUsers (\Closure $callback);
+
 	/**
 	 * @param string $email
 	 * @return IUser[]
diff --git a/tests/lib/Repair/RemoveRootSharesTest.php b/tests/lib/Repair/RemoveRootSharesTest.php
index bf255fc7e9bb9cfbfccf33e58d9508507dad0460..cfb81cb1ecca2d9f94878885d03432fb37e3f5c4 100644
--- a/tests/lib/Repair/RemoveRootSharesTest.php
+++ b/tests/lib/Repair/RemoveRootSharesTest.php
@@ -106,6 +106,7 @@ class RemoveRootSharesTest extends \Test\TestCase {
 		$user = $this->userManager->createUser('test', 'test');
 		$userFolder = $this->rootFolder->getUserFolder('test');
 		$fileId = $userFolder->getId();
+		$user->updateLastLoginTimestamp();
 
 		//Now insert cyclic share
 		$qb = $this->connection->getQueryBuilder();
@@ -134,6 +135,7 @@ class RemoveRootSharesTest extends \Test\TestCase {
 		$user1 = $this->userManager->createUser('test1', 'test1');
 		$userFolder = $this->rootFolder->getUserFolder('test1');
 		$fileId = $userFolder->getId();
+		$user1->updateLastLoginTimestamp();
 
 		//Now insert cyclic share
 		$qb = $this->connection->getQueryBuilder();
@@ -156,6 +158,7 @@ class RemoveRootSharesTest extends \Test\TestCase {
 		$userFolder = $this->rootFolder->getUserFolder('test2');
 		$folder = $userFolder->newFolder('foo');
 		$fileId = $folder->getId();
+		$user2->updateLastLoginTimestamp();
 
 		//Now insert cyclic share
 		$qb = $this->connection->getQueryBuilder();
diff --git a/tests/lib/User/ManagerTest.php b/tests/lib/User/ManagerTest.php
index f6318ff353b01bae94da3c29e9825fcbf601669b..8cad7f4241a391baf4451fc13bdeb261179da624 100644
--- a/tests/lib/User/ManagerTest.php
+++ b/tests/lib/User/ManagerTest.php
@@ -9,6 +9,8 @@
 
 namespace Test\User;
 use OC\User\Database;
+use OCP\IUser;
+use Test\TestCase;
 
 /**
  * Class ManagerTest
@@ -17,7 +19,7 @@ use OC\User\Database;
  *
  * @package Test\User
  */
-class ManagerTest extends \Test\TestCase {
+class ManagerTest extends TestCase {
 	public function testGetBackends() {
 		$userDummyBackend = $this->createMock(\Test\Util\User\Dummy::class);
 		$manager = new \OC\User\Manager();
@@ -448,6 +450,66 @@ class ManagerTest extends \Test\TestCase {
 		$this->assertEquals(7 + 16, $users);
 	}
 
+	public function testCountUsersOnlySeen() {
+		$manager = \OC::$server->getUserManager();
+		// count other users in the db before adding our own
+		$countBefore = $manager->countUsers(true);
+
+		//Add test users
+		$user1 = $manager->createUser('testseencount1', 'testseencount1');
+		$user1->updateLastLoginTimestamp();
+
+		$user2 = $manager->createUser('testseencount2', 'testseencount2');
+		$user2->updateLastLoginTimestamp();
+
+		$user3 = $manager->createUser('testseencount3', 'testseencount3');
+
+		$user4 = $manager->createUser('testseencount4', 'testseencount4');
+		$user4->updateLastLoginTimestamp();
+
+		$this->assertEquals($countBefore + 3, $manager->countUsers(true));
+
+		//cleanup
+		$user1->delete();
+		$user2->delete();
+		$user3->delete();
+		$user4->delete();
+	}
+
+	public function testCallForSeenUsers() {
+		$manager = \OC::$server->getUserManager();
+		// count other users in the db before adding our own
+		$count = 0;
+		$function = function (IUser $user) use (&$count) {
+			$count++;
+		};
+		$manager->callForAllUsers($function, '', true);
+		$countBefore = $count;
+
+		//Add test users
+		$user1 = $manager->createUser('testseen1', 'testseen1');
+		$user1->updateLastLoginTimestamp();
+
+		$user2 = $manager->createUser('testseen2', 'testseen2');
+		$user2->updateLastLoginTimestamp();
+
+		$user3 = $manager->createUser('testseen3', 'testseen3');
+
+		$user4 = $manager->createUser('testseen4', 'testseen4');
+		$user4->updateLastLoginTimestamp();
+
+		$count = 0;
+		$manager->callForAllUsers($function, '', true);
+
+		$this->assertEquals($countBefore + 3, $count);
+
+		//cleanup
+		$user1->delete();
+		$user2->delete();
+		$user3->delete();
+		$user4->delete();
+	}
+
 	public function testDeleteUser() {
 		$config = $this->getMockBuilder('OCP\IConfig')
 			->disableOriginalConstructor()