diff --git a/CHANGELOG.md b/CHANGELOG.md
index f620cadb99a278291fe993bebd5b719dd6a75273..565f7ec686d293845842682e79557cb4b0f3aca5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
 
 * Regression fix dashlets not working anymore #122
 * Fixed contact Summary tab not loading due to fatal error. See !115 and #122
+* Performance improvements.
 
 # Version 1.69
 
diff --git a/CRM/Dataprocessor/Utils/Smartgroup.php b/CRM/Dataprocessor/Utils/Smartgroup.php
new file mode 100644
index 0000000000000000000000000000000000000000..bcc6ab5af3d00a467119521cadee0d1eadc0cf77
--- /dev/null
+++ b/CRM/Dataprocessor/Utils/Smartgroup.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Copyright (C) 2023  Jaap Jansma (jaap.jansma@civicoop.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+class CRM_Dataprocessor_Utils_Smartgroup {
+
+  public static function checkOrRefresh(array $groupIds, $timeOut=120) {
+    $key = 'dataprocessor_smartgroup_check_'.md5(json_encode($groupIds));
+    $cache = CRM_Dataprocessor_Utils_Cache::singleton();
+    $lastCheckTime = $cache->get($key);
+    $timeOut = time() - $timeOut;
+    if (empty($toCheck) || $lastCheckTime < $timeOut) {
+      CRM_Contact_BAO_GroupContactCache::check($groupIds);
+      $cache->set($key, time());
+    }
+  }
+
+}
diff --git a/CRM/DataprocessorSearch/Form/AbstractSearch.php b/CRM/DataprocessorSearch/Form/AbstractSearch.php
index 374862244b058ec1a62909db4ac1794e78f8291d..b957a77b308575324e9c261303c01e46b45bda26 100644
--- a/CRM/DataprocessorSearch/Form/AbstractSearch.php
+++ b/CRM/DataprocessorSearch/Form/AbstractSearch.php
@@ -645,7 +645,7 @@ abstract class CRM_DataprocessorSearch_Form_AbstractSearch extends CRM_Dataproce
   public function allRecordsSelected(): bool {
     if (isset($this->_formValues['radio_ts']) && $this->_formValues['radio_ts'] == 'ts_all') {
       return true;
-    } elseif (!isset($this->_formValues['radio_ts'])) {
+    } elseif (!isset($this->_formValues['radio_ts']) || $this->_formValues['radio_ts'] === "") {
       return true;
     }
     return false;
diff --git a/Civi/DataProcessor/DataFlow/SqlDataFlow/InTableWhereClause.php b/Civi/DataProcessor/DataFlow/SqlDataFlow/InTableWhereClause.php
index f449ba82f6c802e404c2b1f64a43104fd5faa24b..dc103b6c1b04f039a16b0359d7397062166c4b4c 100644
--- a/Civi/DataProcessor/DataFlow/SqlDataFlow/InTableWhereClause.php
+++ b/Civi/DataProcessor/DataFlow/SqlDataFlow/InTableWhereClause.php
@@ -22,6 +22,8 @@ class InTableWhereClause extends AbstractWhereClause implements WhereClauseInter
 
   protected $operator;
 
+  protected $indexStatement = "";
+
   /**
    * @var bool
    */
@@ -38,6 +40,11 @@ class InTableWhereClause extends AbstractWhereClause implements WhereClauseInter
     $this->source_table_alias = $source_table_alias;
   }
 
+  public function setIndexStatement(string $indexStatement): InTableWhereClause {
+    $this->indexStatement = $indexStatement;
+    return $this;
+  }
+
   /**
    * Returns the where clause
    * E.g. contact_type = 'Individual'
@@ -55,7 +62,7 @@ class InTableWhereClause extends AbstractWhereClause implements WhereClauseInter
 
     return "`$this->source_table_alias`.`$this->source_field` $this->operator (
               SELECT `$this->table_alias`.`$this->select_field`
-              FROM `$this->table` `$this->table_alias`
+              FROM `$this->table` `$this->table_alias` $this->indexStatement
               WHERE $whereClause
       )";
   }
diff --git a/Civi/DataProcessor/FilterHandler/ContactHasContributionInPeriod.php b/Civi/DataProcessor/FilterHandler/ContactHasContributionInPeriod.php
index 0e77b74e862d8754b8072d8634f41b18153688cb..5970c6aaf283a3a728adc1118f70a3fb94248c43 100644
--- a/Civi/DataProcessor/FilterHandler/ContactHasContributionInPeriod.php
+++ b/Civi/DataProcessor/FilterHandler/ContactHasContributionInPeriod.php
@@ -268,13 +268,14 @@ class ContactHasContributionInPeriod extends AbstractFieldInPeriodFilter {
           SELECT `contact_id`
           FROM `civicrm_contribution` `c_$fieldAlias`
           WHERE 1";
-        if (isset($filterParams['status_ids']) && is_array($filterParams['status_ids']) && count($filterParams['status_ids'])) {
-          $baseSqlStatement .= " AND `c_$fieldAlias`.`contribution_status_id` IN (" . implode(",", $filterParams['status_ids']) . ")";
-        }
         if (isset($filterParams['financial_type_ids']) && is_array($filterParams['financial_type_ids']) && count($filterParams['financial_type_ids'])) {
           $baseSqlStatement .= " AND `c_$fieldAlias`.`financial_type_id` IN (" . implode(",", $filterParams['financial_type_ids']) . ")";
         }
         $baseSqlStatement .= " AND " . $this->getDateSqlStatement('c_'.$fieldAlias, 'receive_date', $filterParams);
+        $baseSqlStatement .= " AND `c_$fieldAlias`.`is_test` = 0";
+        if (isset($filterParams['status_ids']) && is_array($filterParams['status_ids']) && count($filterParams['status_ids'])) {
+          $baseSqlStatement .= " AND `c_$fieldAlias`.`contribution_status_id` IN (" . implode(",", $filterParams['status_ids']) . ")";
+        }
         $includeCampaignIds = [];
         $excludeCampaignIds = [];
         if (isset($filterParams['campaign_ids']) && is_array($filterParams['campaign_ids']) && count($filterParams['campaign_ids'])) {
diff --git a/Civi/DataProcessor/FilterHandler/ContactInGroupFilter.php b/Civi/DataProcessor/FilterHandler/ContactInGroupFilter.php
index cc21de1756e3583d4b1d9ba21b336d216e9e09e5..52dfa9044c37a8e2a0d694c42eeb0c9789c539a1 100644
--- a/Civi/DataProcessor/FilterHandler/ContactInGroupFilter.php
+++ b/Civi/DataProcessor/FilterHandler/ContactInGroupFilter.php
@@ -67,18 +67,19 @@ class ContactInGroupFilter extends AbstractFieldFilterHandler {
 
     // If the groups are smartgroups (saved searches) they may be out of date.
     // This triggers a check (and rebuild if necessary).
-    \CRM_Contact_BAO_GroupContactCache::check($group_ids);
+    \CRM_Dataprocessor_Utils_Smartgroup::checkOrRefresh($group_ids);
+
 
-    // Look in the group contact table
-    $groupTableAlias = 'civicrm_group_contact_'.$this->inputFieldSpecification->alias;
-    $groupFilters = array(
-      new SqlDataFlow\SimpleWhereClause($groupTableAlias, 'status', '=', 'Added'),
-      new SqlDataFlow\SimpleWhereClause($groupTableAlias, 'group_id', 'IN', $group_ids),
-    );
 
     if ($dataFlow && $dataFlow instanceof SqlDataFlow) {
+      // Look in the group contact table
+      $groupTableAlias = 'civicrm_group_contact_'.$this->inputFieldSpecification->alias;
+      $groupFilters = array(
+        new SqlDataFlow\SimpleWhereClause($groupTableAlias, 'status', '=', 'Added'),
+        new SqlDataFlow\SimpleWhereClause($groupTableAlias, 'group_id', 'IN', $group_ids),
+      );
       $tableAlias = $this->getTableAlias($dataFlow);
-      $this->whereClause = new SqlDataFlow\InTableWhereClause(
+      $groupWhereClause = new SqlDataFlow\InTableWhereClause(
         'contact_id',
         'civicrm_group_contact',
         $groupTableAlias,
@@ -87,28 +88,25 @@ class ContactInGroupFilter extends AbstractFieldFilterHandler {
         $this->inputFieldSpecification->getName(),
         $filter['op']
       );
-      $whereClauses[] = $this->whereClause;
-    }
-
-    // Now look in the smartgroup group contact table
-    $groupTableAlias = 'civicrm_group_contact_cache_'.$this->inputFieldSpecification->alias;
-    $groupFilters = array(
-      new SqlDataFlow\SimpleWhereClause($groupTableAlias, 'group_id', 'IN', $group_ids),
-    );
+      $whereClauses[] = $groupWhereClause;
 
-    if ($dataFlow && $dataFlow instanceof SqlDataFlow) {
+      // Now look in the smartgroup group contact table
+      $smartGroupTableAlias = 'civicrm_group_contact_cache_'.$this->inputFieldSpecification->alias;
+      $smartGroupFilters = array(
+        new SqlDataFlow\SimpleWhereClause($smartGroupTableAlias, 'group_id', 'IN', $group_ids),
+      );
       $tableAlias = $this->getTableAlias($dataFlow);
-      $this->whereClause = new SqlDataFlow\InTableWhereClause(
+      $smartGroupWhereClause = new SqlDataFlow\InTableWhereClause(
         'contact_id',
         'civicrm_group_contact_cache',
-        $groupTableAlias,
-        $groupFilters,
+        $smartGroupTableAlias,
+        $smartGroupFilters,
         $tableAlias,
         $this->inputFieldSpecification->getName(),
         $filter['op']
       );
-
-      $whereClauses[] = $this->whereClause;
+      $smartGroupWhereClause->setIndexStatement('USE INDEX (`UI_contact_group`)');
+      $whereClauses[] = $smartGroupWhereClause;
     }
     switch ($filter['op']) {
       case 'IN':