4

у меня есть проблемы с пониманием пути плана couchbase запрос работает. Я использую SpringData с Couchbase 4.1, и я предоставляю собственную реализацию репозитория Couchbase. Внутри моего пользовательского implememtnation из Couchbase Repository У меня есть ниже метод:Couchbase использует неправильные индексы с N1QL параметризованных запросов

String queryAsString = "SELECT MyDatabase.*, META().id as _ID, META().cas as _CAS FROM MyDatabase WHERE segmentId = $id AND _class = $class ORDER BY executionTime DESC LIMIT 1"; 
JsonObject params = JsonObject.create() 
     .put(CLASS_VARIABLE, MyClass.class.getCanonicalName()) 
     .put(ID_VARIABLE, segmentId); 

N1qlQuery query = N1qlQuery.parameterized(queryAsString, params); 
List<MyClass> resultList = couchbaseTemplate.findByN1QL(query, SegmentMembers.class); 
return resultList.isEmpty() ? null : resultList.get(0); 

В результате Spring Data производит следующий объект JSON представлен запрос на Couchbase:

{ 
    "$class":"path/MyClass", 
    "statement":"SELECT MyDatabase.*, META().id as _ID, META().cas as _CAS from MyDatabase where segmentId = $id AND _class = $class ORDER BY executionTime DESC LIMIT 1", 
    "id":"6592c16a-c8ae-4a74-bc17-7e18bf73b3f8" 
} 

И проблема с производительностью, когда я исполняю это через Java и N1QL Rest Api или через консоль cbq. Для выполнения этого запроса в cbq я просто заменяю ссылки параметров точными значениями.

После добавления EXPLAIN пункта перед тем отборным заявлением я упомянул различные планы выполнения. Выполнение этого запроса в параметризованном запросе через Java Spring Data или N1QL Rest Api. Я упомянул, что в запросе не используется индекс, который я создал именно для этого случая. Индекс Definiton можно найти ниже:

CREATE INDEX `testMembers` ON MyDatabase `m`(`_class`,`segmentId`,`executionTime`) WHERE (`_class` = "path/MyClass") USING GSI; 

Так что, когда я выполнить запрос с помощью CBQ Consol, Couchbase использует мой idnex и производительность запросов очень хорошо. Но когда я выполняю этот запрос через N1QL rest api или Java, я вижу, что этот запрос не использует мой индекс. Ниже вы можете найти часть плана исполнения, что подтверждает этот факт:

"~children": [ 
{ 
    "#operator": "PrimaryScan", 
    "index": "#primary", 
    "keyspace": "CSM", 
    "namespace": "default", 
    "using": "gsi" 
}, 

Итак, вопрос заключается в том, что право и правовое поведение оптимизатора couchbase запроса? И означает ли это, что в плане запроса не учитываются реальные значения параметров? И нужно ли вручную вставлять значения в строку запроса или использовать другой способ использования параметризованного запроса N1Ql с правильным выбором индекса?

EDIT

Согласно Шаш Раджа ответа АПЧРК (ложь) параметр для параметризованного запроса N1QL добавить N1qlParams.build().. Это не решает мою проблему, потому что у меня все еще есть проблемы с производительностью с этим запросом. Более того, когда я печатаю запрос, я вижу, что он такой же, как я описал ранее. Таким образом, мой запрос все еще ошибочно анализируется и приводит к снижению производительности.

+0

Вы можете попробовать Couchbase 4.5.1, чтобы увидеть, если это было исправлено. – geraldss

+0

Нет, это не исправлено даже в 4.6 – gaperton

+0

И, видимо, нечего исправить :). См. Мой ответ ниже. – gaperton

ответ

1

Проблема в вашем случае вызвана тем, что у вас есть индекс с предложением «где» WHERE (_class = "path/MyClass") и в то же время вы передаете _class в качестве параметра в запросе.

Таким образом, оптимизатор запросов, анализирующий параметризованный запрос, не имеет представления, что этот запрос может использовать индекс, созданный для _class = "path/MyClass", потому что это _class = $class в select. Довольно просто, не так ли?

Итак, не указывайте ни одного поля, указанного в разделе «где» вашего индекса в качестве параметров. Вместо этого, hardcode _class = "path/MyClass" в вашем выбрать таким же образом, как вы сделали для create index. И все должно быть хорошо.

Вот этот билет в системе отслеживания проблем couchbase об этом.

https://issues.couchbase.com/browse/MB-22185?jql=text%20~%20%22parameters%20does%20not%20use%20index%22

2

первую очередь вы должны знать, как N1QL параметризованных запросов работает запрос должен быть передан как:

String query= select * from bucketName where _class=$_class and segmentId=$segmentId LIMIT $limit ; 

Теперь запрос должен быть передан как:

N1QL.parameterized(query,jsonObject,N1qlParams.build().adhoc(false)); 

где jsonObject будет иметь все значения заполнителя.

JsonObject jsonObject=JsonObject.create().put("_class","com.entity,user").put("segmentId","12345").put("limit",100); 

N1qlParams.build().adhoc(false) не является обязательным, так как если вы хотите, чтобы ваш запрос должен быть оптимизирован будет использовать его. Он использует LRU, где он отслеживает ранее введенный запрос и сохраняет его запись, поэтому в следующий раз ему не нужно анализировать запрос и извлекать его из предыдущего, что мы называем подготовленным оператором.

Единственная проблема couchbase только хранит запись о последних 5000 запросе.

+0

Извините, но это не решило мою проблему. У меня все еще есть проблемы с производительностью. Даже если я создаю запрос с указанным флагом на false. Возможно, у вас есть другие предложения? – 4the3eam

+0

Попробуйте использовать индексы покрытия, они решают большинство проблем с производительностью. Предположим, что если вы хотите запросить использование 5 атрибутов, укажите эти атрибуты при создании индекса –

+0

. Убедитесь, что maaping переменной в запросе n объект Json должен быть таким же. В противном случае это не сработает. –

Смежные вопросы