Skip to content

Search performance/speed question on negative query #1828

@thoriqsatriya

Description

@thoriqsatriya

Hi, I want to use bleve to search from slice of struct but I have performance issue.

I want to search exact match with one of the field, sometimes I need negative search and sometimes positive. I don't need to use full text search for this case. Here is what I found so far:

  1. Search using negative search will have much slower performance even when the result count is around the same? I would expect it to be the same because it returns same number of hits
  2. Search on struct with fewer field will have faster performance, compared when the struct has more field. I would expect it to be the same because I only search on one field. On SQL, it will be select field from table, it should not have noticeable performance difference when the table has more field or not
  3. How to disable full text search?

Anyone know what I'm doing wrong here? And how to achieve what I want? Thank you

Here is the result:

negative search on simplified struct: 7.718755ms
negative search on normal struct: 10.91501ms
positive search on simplified struct: 2.358683ms
positive search on normal struct: 2.237731ms

Here is my code:

package main

import (
	"fmt"
	"github.com/blevesearch/bleve/v2"
	"github.com/google/uuid"
	"math/rand"
	"time"
)

type UserSimple struct {
	Age         int    `json:"age"`
	ID          string `json:"id"`
	Nationality string `json:"nationality"`
}

type User struct {
	Age         int    `json:"age"`
	ID          string `json:"id"`
	Nationality string `json:"nationality"`
	Field       string `json:"field"`
	Field2      string `json:"field2"`
	Field3      string `json:"field3"`
	Field4      string `json:"field4"`
	Field5      string `json:"field5"`
	Field6      string `json:"field6"`
}

func main() {
	mapping := bleve.NewIndexMapping()
	index, err := bleve.NewMemOnly(mapping)
	if err != nil {
		panic(err)
	}
	defer func() { _ = index.Close() }()

	index2, err := bleve.NewMemOnly(mapping)
	if err != nil {
		panic(err)
	}
	defer func() { _ = index2.Close() }()

	for i := 0; i < 1000; i++ {
		userID := uuid.NewString()

		err = index.Index(userID, UserSimple{
			Age:         rand.Int(),
			ID:          userID,
			Nationality: "US",
		})
		if err != nil {
			panic(err)
		}

		err = index2.Index(userID, User{
			Age:         rand.Int(),
			ID:          userID,
			Nationality: "US",
			Field:       userID,
			Field2:      userID,
			Field3:      userID,
			Field4:      userID,
			Field5:      userID,
			Field6:      userID,
		})
		if err != nil {
			panic(err)
		}
	}

	err = index.Index("test", UserSimple{
		Age: 20,
		ID:  "test",
	})
	if err != nil {
		panic(err)
	}

	err = index2.Index("test", User{
		Age: 20,
		ID:  "test",
	})
	if err != nil {
		panic(err)
	}

	n := 100
	var totalDurNegativeStruct1 time.Duration
	var totalDurNegativeStruct2 time.Duration
	var totalDurPositiveStruct1 time.Duration
	var totalDurPositiveStruct2 time.Duration

       // iterate n times to find the average
	for i := 0; i < n; i++ {
		queryNegative := bleve.NewQueryStringQuery("-id:test")
		searchNegative := bleve.NewSearchRequestOptions(queryNegative, 10, 0, false)
		searchNegative.Size = 1000

		queryPositive := bleve.NewQueryStringQuery("nationality:US")
		searchPositive := bleve.NewSearchRequestOptions(queryPositive, 10, 0, false)
		searchPositive.Size = 1000

		resultNegative, errQuery := index.Search(searchNegative)
		if errQuery != nil {
			panic(errQuery)
		}
		totalDurNegativeStruct1 += resultNegative.Took

		resultNegative2, errQuery := index2.Search(searchNegative)
		if errQuery != nil {
			panic(errQuery)
		}
		totalDurNegativeStruct2 += resultNegative2.Took

		resultPositive, errQuery := index.Search(searchPositive)
		if errQuery != nil {
			panic(errQuery)
		}
		totalDurPositiveStruct1 += resultPositive.Took

		resultPositive2, errQuery := index2.Search(searchPositive)
		if errQuery != nil {
			panic(errQuery)
		}
		totalDurPositiveStruct2 += resultPositive2.Took
	}

	fmt.Println(time.Duration(int64(totalDurNegativeStruct1) / int64(n)))
	fmt.Println(time.Duration(int64(totalDurNegativeStruct2) / int64(n)))

	fmt.Println(time.Duration(int64(totalDurPositiveStruct1) / int64(n)))
	fmt.Println(time.Duration(int64(totalDurPositiveStruct2) / int64(n)))
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions