diff --git a/CHANGELOG.md b/CHANGELOG.md
index c66132c38d8318406b584949cfdda8635c8a1774..3c07ca181104f022b60cbf6d1896d3046d2c143f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -31,8 +31,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Removed ###
 
 ### Fixed ###
-- [#203](https://gitlab.com/caosdb/caosdb-server/-/issues/203)
 
+* Bad performance due to the execution of unnecessary jobs during retrieval.
+  [#189](https://gitlab.com/caosdb/caosdb-server/-/issues/189)
+* Query Language: Parentheses change filter to subproperty filter
+  [#203](https://gitlab.com/caosdb/caosdb-server/-/issues/203)
 * Searching for values in scientific notation
   [#143](https://gitlab.com/caosdb/caosdb-server/-/issues/143)
 * Denying a role permission has no effect
diff --git a/src/main/java/org/caosdb/server/entity/Entity.java b/src/main/java/org/caosdb/server/entity/Entity.java
index 2668e770d6f779e0b3121f30aa1778dccf6c9d93..48367508112c2c3267abd771fa84eb21ea16a534 100644
--- a/src/main/java/org/caosdb/server/entity/Entity.java
+++ b/src/main/java/org/caosdb/server/entity/Entity.java
@@ -1004,7 +1004,7 @@ public abstract class Entity extends AbstractObservable implements EntityInterfa
 
   @Override
   public boolean skipJob() {
-    return false;
+    return this.entityStatus == EntityStatus.IGNORE;
   }
 
   @Override
diff --git a/src/main/java/org/caosdb/server/entity/xml/ParentToElementStrategy.java b/src/main/java/org/caosdb/server/entity/xml/ParentToElementStrategy.java
index 4f7906829427a2305f0f1b2addf72d2b69112a9e..2556fdb21bbb55252144a4200f75a265a562af74 100644
--- a/src/main/java/org/caosdb/server/entity/xml/ParentToElementStrategy.java
+++ b/src/main/java/org/caosdb/server/entity/xml/ParentToElementStrategy.java
@@ -26,7 +26,6 @@ package org.caosdb.server.entity.xml;
 
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.wrapper.Parent;
-import org.caosdb.server.utils.EntityStatus;
 import org.jdom2.Element;
 
 /**
@@ -51,15 +50,4 @@ public class ParentToElementStrategy extends EntityToElementStrategy {
     }
     return element;
   }
-
-  @Override
-  public Element addToElement(
-      final EntityInterface entity,
-      final Element element,
-      final SerializeFieldStrategy setFieldStrategy) {
-    if (entity.getEntityStatus() != EntityStatus.IGNORE) {
-      element.addContent(toElement(entity, setFieldStrategy));
-    }
-    return element;
-  }
 }
diff --git a/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java b/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java
index 5c9f4c2ca13f8481d075117cb34dec41e5aeeab8..2d7a45d099fa5bec35586b58257eb2c71d61cbe0 100644
--- a/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java
+++ b/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java
@@ -31,15 +31,20 @@ import org.caosdb.server.jobs.JobAnnotation;
 import org.caosdb.server.jobs.TransactionStage;
 import org.caosdb.server.query.Query;
 import org.caosdb.server.query.Query.ParsingException;
+import org.caosdb.server.transaction.Retrieve;
+import org.caosdb.server.utils.EntityStatus;
 import org.caosdb.server.utils.ServerMessages;
 
-@JobAnnotation(flag = "query", stage = TransactionStage.INIT)
+@JobAnnotation(flag = "query", stage = TransactionStage.INIT, transaction = Retrieve.class)
 public class ExecuteQuery extends FlagJob {
 
   @Override
   protected void job(final String value) {
 
     if (value != null) {
+      // run paging job first
+      getTransaction().getSchedule().runJob(null, Paging.class);
+
       final Query queryInstance =
           new Query(value, getTransaction().getTransactor(), getContainer());
       getContainer().setQuery(queryInstance);
@@ -53,8 +58,24 @@ public class ExecuteQuery extends FlagJob {
             .addMessage(new Message(MessageType.Info, (MessageCode) null, e.getMessage()));
       }
       getContainer().addMessage(queryInstance);
+
+      int startIndex = 0;
+      int endIndex = getContainer().size();
+
+      if (((Retrieve) getTransaction()).hasPaging()) {
+        Retrieve.Paging paging = ((Retrieve) getTransaction()).getPaging();
+        startIndex = Math.min(getContainer().size(), paging.startIndex);
+        endIndex = Math.min(getContainer().size(), paging.endIndex);
+      }
+
+      int ii = 0;
       for (final EntityInterface entity : getContainer()) {
-        getTransaction().getSchedule().addAll(loadJobs(entity, getTransaction()));
+        if (ii >= startIndex && ii < endIndex) {
+          getTransaction().getSchedule().addAll(loadJobs(entity, getTransaction()));
+        } else {
+          entity.setEntityStatus(EntityStatus.IGNORE);
+        }
+        ii++;
       }
     }
   }
diff --git a/src/main/java/org/caosdb/server/jobs/core/Paging.java b/src/main/java/org/caosdb/server/jobs/core/Paging.java
index 5f2a6ed62f48f20d09c34c8ee34190231903ffe7..aa918ecfe2ac20b90b019b5ace91bde05ccac9ef 100644
--- a/src/main/java/org/caosdb/server/jobs/core/Paging.java
+++ b/src/main/java/org/caosdb/server/jobs/core/Paging.java
@@ -31,7 +31,7 @@ import org.caosdb.server.jobs.TransactionStage;
 import org.caosdb.server.transaction.Retrieve;
 import org.caosdb.server.utils.EntityStatus;
 
-@JobAnnotation(flag = "P", stage = TransactionStage.PRE_TRANSACTION)
+@JobAnnotation(flag = "P", stage = TransactionStage.INIT, transaction = Retrieve.class)
 public class Paging extends FlagJob {
 
   public static final int DEFAULT_LENGTH = 100;
@@ -42,20 +42,24 @@ public class Paging extends FlagJob {
   protected void job(final String value) {
     if (getTransaction() instanceof Retrieve) {
       if (value != null) {
-        int index1 = DEFAULT_INDEX;
-        int index2 = index1 + DEFAULT_LENGTH;
+        int startIndex = DEFAULT_INDEX;
+        int endIndex = startIndex + DEFAULT_LENGTH;
         final Matcher m = pattern.matcher(value);
         if (m.matches()) {
           if (m.group(1) != null) {
-            index1 = Integer.parseInt(m.group(1));
+            startIndex = Integer.parseInt(m.group(1));
           }
           if (m.group(2) != null) {
-            index2 = index1 + Integer.parseInt(m.group(2));
+            endIndex = startIndex + Integer.parseInt(m.group(2));
           }
         }
+
+        // this info may be used by other jobs
+        ((Retrieve) getTransaction()).setPaging(startIndex, endIndex);
+
         int i = 0;
         for (final EntityInterface e : getContainer()) {
-          if (i >= index2 || i < index1) {
+          if (i >= endIndex || i < startIndex) {
             // do not retrieve this entity
             e.setEntityStatus(EntityStatus.IGNORE);
           }
diff --git a/src/main/java/org/caosdb/server/jobs/core/RetrieveAllJob.java b/src/main/java/org/caosdb/server/jobs/core/RetrieveAllJob.java
index 7cd7791e0b27f1ec1d5e67e047e7f1cbe177948c..a89385e29f458ad3ad15eea0d9e6b6bf7640bca6 100644
--- a/src/main/java/org/caosdb/server/jobs/core/RetrieveAllJob.java
+++ b/src/main/java/org/caosdb/server/jobs/core/RetrieveAllJob.java
@@ -27,19 +27,43 @@ import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.jobs.FlagJob;
 import org.caosdb.server.jobs.JobAnnotation;
 import org.caosdb.server.jobs.TransactionStage;
+import org.caosdb.server.transaction.Retrieve;
+import org.caosdb.server.utils.EntityStatus;
 
-@JobAnnotation(flag = "all", stage = TransactionStage.INIT)
+@JobAnnotation(flag = "all", stage = TransactionStage.INIT, transaction = Retrieve.class)
 public class RetrieveAllJob extends FlagJob {
 
   @Override
   protected void job(String value) {
     if (getContainer().isEmpty()) {
+      // run paging job first
+      getTransaction().getSchedule().runJob(null, Paging.class);
+
       if (value == null) {
         value = "ENTITY";
       }
+
       execute(new RetrieveAll(getContainer(), value));
+
+      int startIndex = 0;
+      int endIndex = getContainer().size();
+
+      if (((Retrieve) getTransaction()).hasPaging()) {
+        startIndex =
+            Math.min(getContainer().size(), ((Retrieve) getTransaction()).getPaging().startIndex);
+        endIndex =
+            Math.min(getContainer().size(), ((Retrieve) getTransaction()).getPaging().endIndex);
+      }
+
+      // only add jobs for those which are on this page
+      int ii = 0;
       for (EntityInterface entity : getContainer()) {
-        getTransaction().getSchedule().addAll(loadJobs(entity, getTransaction()));
+        if (ii >= startIndex && ii < endIndex) {
+          getTransaction().getSchedule().addAll(loadJobs(entity, getTransaction()));
+        } else {
+          entity.setEntityStatus(EntityStatus.IGNORE);
+        }
+        ii++;
       }
     }
   }
diff --git a/src/main/java/org/caosdb/server/transaction/Retrieve.java b/src/main/java/org/caosdb/server/transaction/Retrieve.java
index 86b7672cf9ebc0ad8e74f3974ee89174532d9f73..643c1201b530af9821c9a5c1a7b62f7c5d04cf52 100644
--- a/src/main/java/org/caosdb/server/transaction/Retrieve.java
+++ b/src/main/java/org/caosdb/server/transaction/Retrieve.java
@@ -121,4 +121,28 @@ public class Retrieve extends Transaction<RetrieveContainer> {
   public boolean logHistory() {
     return false;
   }
+
+  public static class Paging {
+    public Paging(int startIndex, int endIndex) {
+      this.startIndex = startIndex;
+      this.endIndex = endIndex;
+    }
+
+    public final int startIndex;
+    public final int endIndex;
+  }
+
+  private Retrieve.Paging paging = null;
+
+  public boolean hasPaging() {
+    return this.paging != null;
+  }
+
+  public void setPaging(int startIndex, int endIndex) {
+    this.paging = new Retrieve.Paging(startIndex, endIndex);
+  }
+
+  public Retrieve.Paging getPaging() {
+    return paging;
+  }
 }
diff --git a/src/main/java/org/caosdb/server/transaction/Transaction.java b/src/main/java/org/caosdb/server/transaction/Transaction.java
index b4d63fbb293e0119cefe90db34b9cfb28f4e0ce1..5fc06f5ec82066d3515cbf524e64beb001ba0fcd 100644
--- a/src/main/java/org/caosdb/server/transaction/Transaction.java
+++ b/src/main/java/org/caosdb/server/transaction/Transaction.java
@@ -105,6 +105,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
     this.schedule.addAll(Job.loadPermanentContainerJobs(this));
 
     for (final EntityInterface e : getContainer()) {
+      if (e.skipJob()) continue;
       final List<Job> loadJobs = loadContainerFlags.loadJobs(e, this);
       this.schedule.addAll(loadJobs);