Как правильно использовать вторичный индекс для весенних данных

У меня есть корзина couchbase с именем order, которая содержит почти 2000 документов, я создал вторичный индекс (idx_customer) для этого ведра, чтобы оптимизировать свои запросы:

Запрос попадает в индекс при выполнении в мониторе запросов couchbase.

но я думаю, что он пропускает индекс при воспроизведении из весеннего репозитория данных. главным образом потому, что сортировка и разбиение по страницам в репозитории переводят мой запрос в другие запросы, не содержащие индекса.

CREATE INDEX idx_customer ON `order` (
buyer.contact.firstName , 
buyer.contact.lastName , 
ALL DISTINCT ARRAY aoc.`communicationValue` FOR aoc IN buyer.contact.communicationChannel
WHEN aoc.`communicationChannelCode`= "EMAIL" END)
WHERE _class = "com.lbk.entities.OrderEntity"

Я запрашиваю порядок внутри своего весеннего загрузочного приложения, используя весенние данные из этого репозитория:

import com.lbk.entities.OrderEntity;
import com.lbk.entities.OrderMetadataEntity;
import org.springframework.data.couchbase.core.query.N1qlPrimaryIndexed;
import org.springframework.data.couchbase.core.query.N1qlSecondaryIndexed;
import org.springframework.data.couchbase.core.query.Query;
import org.springframework.data.couchbase.core.query.ViewIndexed;
import org.springframework.data.couchbase.repository.CouchbasePagingAndSortingRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.List;

@ViewIndexed(designDoc = "orderEntity")
@N1qlSecondaryIndexed(indexName = "idx_customer")
@N1qlPrimaryIndexed
public interface OrdersRepository extends CouchbasePagingAndSortingRepository<OrderEntity, String> {

    List<OrderMetadataEntity> findAllBy();

    Page<OrderMetadataEntity> findAllBy(Pageable page);

    @Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} "
                    + "AND orderTypeCode = $1 "
                    + "AND (orderCategory != $2 OR orderCategory is not valued ) "
                    + "AND buyer.contact.firstName is not null"
    )
    Page<OrderMetadataEntity> findOrders(String orderTypeCode, String excludedOrderCategory, Pageable page);

    @Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} "
                    + "AND creationDateTime >= STR_TO_MILLIS($1) AND creationDateTime <= STR_TO_MILLIS($2) "
                    + "AND orderTypeCode = $3 "
                    + "AND (orderCategory != $4 OR orderCategory is not valued )"

+ "И имя покупателя.contact.firstName не равно нулю") Page findOrdersByCreationDateTimeBetween (начало строки, конец строки, строка orderTypeCode, String excludedOrderCategory, страница для страницы);

}

Но производительность и регистрация показывают, что я не использую индекс, что не так? и как правильно запросить вторичный индекс из моего репозитория?

для этого выгружаемого запроса N1QL:

@Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} "
                                + "AND orderTypeCode = $1 "
                                + "AND (orderCategory != $2 OR orderCategory is not valued ) "
                                + "AND buyer.contact.firstName is not null")
Page<OrderMetadataEntity> findOrders(String orderTypeCode, String excludedOrderCategory, Pageable page);

У меня текущие три запроса в журналах:

  1. Запрос для подсчета документов.
  2. Запрос на получение первой страницы документов.
  3. Запрос на получение субдокументов (SELECT ARRAY_LENGTH (orderLineItem)) (интересно, почему !!!).

Вот журналы весенних данных:

Executing N1QL query: {\"args\":[\"%mohammed%\",\"%mohammed%\",null,\"220\",\"EXECLUDED_CATEGORY\"],\"statement\":\"SELECT COUNT(*) AS count FROM `order` WHERE `_class` = \\"com.lbk.entities.OrderEntity\\" AND ( LOWER(buyer.contact.firstName) LIKE $1 OR LOWER(buyer.contact.lastName) LIKE $2 OR ANY communicationChannel IN buyer.contact.communicationChannel SATISFIES ( communicationChannel.communicationChannelCode = 'EMAIL' AND communicationChannel.communicationValue  = $3 ) END )  AND orderTypeCode = $4 AND (orderCategory != $5 OR O2.orderCategory is not valued )AND creationDateTime in (select RAW max(O2.creationDateTime) from `order` O2 WHERE ( LOWER(O2.buyer.contact.firstName) LIKE $1 OR LOWER(O2.buyer.contact.lastName) LIKE $2 OR ANY communicationChannel IN O2.buyer.contact.communicationChannel SATISFIES ( communicationChannel.communicationChannelCode = 'EMAIL' AND communicationChannel.communicationValue  = $3 ) END )  AND ANY communicationChannel IN O2.buyer.contact.communicationChannel SATISFIES ( communicationChannel.communicationChannelCode = 'EMAIL' AND communicationChannel.communicationValue is not null ) END AND O2.orderTypeCode = $4 AND (O2.orderCategory != $5 OR O2.orderCategory is not valued) group by ( ARRAY item.communicationValue FOR item IN O2.buyer.contact.communicationChannel WHEN item.communicationChannelCode = 'EMAIL' END ) )AND buyer.contact.firstName IS NOT NULL\",\"scan_consistency\":\"statement_plus\"}
Executing N1QL query: {\"args\":[\"%mohammed%\",\"%mohammed%\",null,\"220\",\"EXECLUDED_CATEGORY\"],\"statement\":\"SELECT META(`order`).id AS _ID, META(`order`).cas AS _CAS, `order`.* FROM `order` WHERE `_class` = \\"com.lbk.entities.OrderEntity\\" AND ( LOWER(buyer.contact.firstName) LIKE $1 OR LOWER(buyer.contact.lastName) LIKE $2 OR ANY communicationChannel IN buyer.contact.communicationChannel SATISFIES ( communicationChannel.communicationChannelCode = 'EMAIL' AND communicationChannel.communicationValue  = $3 ) END )  AND orderTypeCode = $4 AND (orderCategory != $5 OR O2.orderCategory is not valued )AND creationDateTime in (select RAW max(O2.creationDateTime) from `order` O2 WHERE ( LOWER(O2.buyer.contact.firstName) LIKE $1 OR LOWER(O2.buyer.contact.lastName) LIKE $2 OR ANY communicationChannel IN O2.buyer.contact.communicationChannel SATISFIES ( communicationChannel.communicationChannelCode = 'EMAIL' AND communicationChannel.communicationValue  = $3 ) END )  AND ANY communicationChannel IN O2.buyer.contact.communicationChannel SATISFIES ( communicationChannel.communicationChannelCode = 'EMAIL' AND communicationChannel.communicationValue is not null ) END AND O2.orderTypeCode = $4 AND (O2.orderCategory != $5 OR O2.orderCategory is not valued) group by ( ARRAY item.communicationValue FOR item IN O2.buyer.contact.communicationChannel WHEN item.communicationChannelCode = 'EMAIL' END ) )AND buyer.contact.firstName IS NOT NULL ORDER BY `creationDateTime` DESC LIMIT 18 OFFSET 0\",\"scan_consistency\":\"statement_plus\"}
Executing N1QL query: {\"args\":[\"069cf983-8ed7-4b8f-845d-175593d4ca49\"],\"statement\":\"SELECT ARRAY_LENGTH(orderLineItem) FROM `order` WHERE `_class` = \\"com.lbk.entities.OrderEntity\\" AND META().id = $1\",\"scan_consistency\":\"statement_plus\"}

Спасибо


person Lho Ben    schedule 06.01.2019    source источник


Ответы (1)


Запросы не смогут использовать индекс idx_customer, потому что он не соответствует требованиям. Ознакомьтесь с разделом «Разработка индекса для запросов в Couchbase N1QL» в https://blog.couchbase.com/n1ql-practical-guide-second-edition

Индекс является частичным и содержит только записи для документа с _class = "com.lbk.entities.OrderEntity", но ни один из ваших запросов не будет иметь этого предиката, поэтому он не может использовать этот индекс. Кроме того, для использования индекса предикат запроса (каждая часть предиката OR) должен иметь ведущий ключ индекса в качестве предиката запроса. Это не относится к запросам в журнале. Если хотите, можете попробовать неполный индекс.

CREATE INDEX idx_customer1 ON `order` (_class, 
buyer.contact.firstName , 
buyer.contact.lastName , 
ALL DISTINCT ARRAY aoc.`communicationValue` FOR aoc IN buyer.contact.communicationChannel
WHEN aoc.`communicationChannelCode`= "EMAIL" END);
person vsr    schedule 06.01.2019
comment
все мои запросы соответствуют индексу, если объяснено в мониторе запросов, _class = com.lbk.entities.OrderEntity добавляется данными Spring для моих первых двух журналов. ведущий индексный ключ добавляется ко всем запросам - person Lho Ben; 07.01.2019
comment
используя ваш предложенный индекс, я получил те же перфомансы. Спасибо за вашу помощь - person Lho Ben; 07.01.2019
comment
Используя этот запрос с вашим индексом: SELECT META (_1 _). Id AS _ID, META (_2 _). Cas AS _CAS, _3 _. * FROM order WHERE _class = com.lbk.entities.OrderEntity AND orderTypeCode = '220' AND (orderCategory ! = 'ИСКЛЮЧЕНО' ИЛИ ​​orderCategory не оценивается) И покупатель.contact.firstName не равно нулю ORDER BY creationDateTime DESC требуется истекло: 6.20 с | исполнение: 6.20 сек | количество: 2345 | размер: 80916114 - person Lho Ben; 07.01.2019
comment
СОЗДАТЬ ИНДЕКС idx_customer2 ON order (orderTypeCode, creationDateTime DESC) ГДЕ _class = com.lbk.entities.OrderEntity - person vsr; 07.01.2019
comment
Большое спасибо Vsr, я наконец думаю, что даже если мои запросы попадут в индекс, возможно, использовать spring-data - плохая идея. - person Lho Ben; 07.01.2019