diff --git a/libursa/QueryOptimizer.cpp b/libursa/QueryOptimizer.cpp
index 726f416..362c76f 100644
--- a/libursa/QueryOptimizer.cpp
+++ b/libursa/QueryOptimizer.cpp
@@ -32,6 +32,27 @@ Query flatten_trivial_operations(Query &&q, bool *changed) {
     return std::move(q);
 }
 
+// This optimization inlines eliglible suboperations:
+// AND(AND(a, b), AND(c, d), e) --> AND(a, b, c, d, e)
+// OR(OR(a, b), OR(c, d), e) --> OR(a, b, c, d, e)
+Query inline_suboperations(Query &&q, bool *changed) {
+    if (q.get_type() != QueryType::AND && q.get_type() != QueryType::OR) {
+        return std::move(q);
+    }
+    std::vector<Query> newqueries;
+    for (auto &&query : q.as_queries()) {
+        if (query.get_type() == q.get_type()) {
+            for (auto &&subquery : query.as_queries()) {
+                newqueries.emplace_back(std::move(subquery));
+            }
+            *changed = true;
+        } else {
+            newqueries.emplace_back(std::move(query));
+        }
+    }
+    return std::move(Query(q.get_type(), std::move(newqueries)));
+}
+
 Query q_optimize(Query &&q) {
     if (q.get_type() == QueryType::PRIMITIVE) {
         // Nothing to improve here.
@@ -43,6 +64,7 @@ Query q_optimize(Query &&q) {
     while (changed) {
         changed = false;
         q = flatten_trivial_operations(std::move(q), &changed);
+        q = inline_suboperations(std::move(q), &changed);
     }
 
     return std::move(q);
diff --git a/libursa/Version.h.in b/libursa/Version.h.in
index f8bc058..e85d3b8 100644
--- a/libursa/Version.h.in
+++ b/libursa/Version.h.in
@@ -9,5 +9,5 @@ constexpr std::string_view ursadb_format_version = "1.5.0";
 // Project version.
 // Consider updating the version tag when doing PRs.
 // clang-format off
-constexpr std::string_view ursadb_version_string = "@PROJECT_VERSION@+opt1";
+constexpr std::string_view ursadb_version_string = "@PROJECT_VERSION@+opt2";
 // clang-format on