Как правильно использовать вторичный индекс для весенних данных - PullRequest
0 голосов
/ 06 января 2019

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

Запрос ударил индекс при выполнении в Couchbase Query Monitor.

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

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 )"

+ "И покупатель.контакт.firstName не является нулевым" ) Страница findOrdersByCreationDateTimeBetween ( Струнное начало, Конец строки, String orderTypeCode, Строка исключеннаяOrderCategory, Pageable страница );

}

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

для этого постраничного запроса 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\"}

Спасибо

1 Ответ

0 голосов
/ 07 января 2019

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

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

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);
...