使用索引的 Hazelcast 分布式查询

Hazelcast distributed query using indexes

我正在尝试使用谓词查询 Hazelcast 地图。我的谓词代码在没有索引的情况下工作正常,但为了获得更好的性能,我想将索引放在 key 我的 Hazelcast 地图上。

映射结构:IMap<Event, Long> - Event 是一个 POJO class。

<map name="event.map">
  <in-memory-format>NATIVE</in-memory-format>
  <backup-count>2</backup-count>
  <async-backup-count>0</async-backup-count>
  <time-to-live-seconds>30</time-to-live-seconds>
  <max-idle-seconds>0</max-idle-seconds>
  <eviction-policy>LFU</eviction-policy>
  <max-size policy="FREE_NATIVE_MEMORY_PERCENTAGE">25</max-size>
  <cache-deserialized-values>INDEX-ONLY</cache-deserialized-values>
  <indexes>
    <index ordered="true">eventType</index>
</indexes>
</map>

使用上面的地图配置,我得到以下异常:

Jul 19, 2019 10:04:21 PM com.hazelcast.map.impl.operation.HDEntryOperation
SEVERE: [127.0.0.1]:5701 [dev] [3.11.2] java.lang.IllegalArgumentException: There is no suitable accessor for 'eventType' on class 'java.lang.Long'
com.hazelcast.query.QueryException: java.lang.IllegalArgumentException: There is no suitable accessor for 'eventType' on class 'java.lang.Long'
        at com.hazelcast.query.impl.getters.ReflectionHelper.createGetter(ReflectionHelper.java:175)
        at com.hazelcast.query.impl.getters.Extractors.instantiateGetter(Extractors.java:124)
        at com.hazelcast.query.impl.getters.Extractors.getGetter(Extractors.java:101)
        at com.hazelcast.query.impl.getters.Extractors.extract(Extractors.java:63)
        at com.hazelcast.query.impl.QueryableEntry.extractAttributeValueFromTargetObject(QueryableEntry.java:144)
        at com.hazelcast.query.impl.QueryableEntry.extractAttributeValue(QueryableEntry.java:82)
        at com.hazelcast.query.impl.QueryableEntry.getAttributeValue(QueryableEntry.java:48)
        at com.hazelcast.query.impl.QueryableEntry.getConverter(QueryableEntry.java:67)
        at com.hazelcast.query.impl.IndexImpl.saveEntryIndex(IndexImpl.java:79)
        at com.hazelcast.query.impl.Indexes.saveEntryIndex(Indexes.java:164)
        at com.hazelcast.map.impl.recordstore.AbstractRecordStore.saveIndex(AbstractRecordStore.java:165)
        at com.hazelcast.map.impl.recordstore.DefaultRecordStore.putInternal(DefaultRecordStore.java:709)
        at com.hazelcast.map.impl.recordstore.DefaultRecordStore.setWithUncountedAccess(DefaultRecordStore.java:987)
        at com.hazelcast.map.impl.operation.EntryOperator.onAddedOrUpdated(EntryOperator.java:288)
        at com.hazelcast.map.impl.operation.EntryOperator.doPostOperateOps(EntryOperator.java:219)
        at com.hazelcast.map.impl.operation.HDEntryOperation.runVanilla(HDEntryOperation.java:257)
        at com.hazelcast.map.impl.operation.HDEntryOperation.runInternal(HDEntryOperation.java:95)
        at com.hazelcast.map.impl.operation.HDMapOperation.run(HDMapOperation.java:88)
        at com.hazelcast.spi.Operation.call(Operation.java:170)
        at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.call(OperationRunnerImpl.java:208)
        at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:197)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationExecutorImpl.run(OperationExecutorImpl.java:407)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationExecutorImpl.runOrExecute(OperationExecutorImpl.java:434)
        at com.hazelcast.spi.impl.operationservice.impl.Invocation.doInvokeLocal(Invocation.java:586)
        at com.hazelcast.spi.impl.operationservice.impl.Invocation.doInvoke(Invocation.java:571)
        at com.hazelcast.spi.impl.operationservice.impl.Invocation.invoke0(Invocation.java:530)
        at com.hazelcast.spi.impl.operationservice.impl.Invocation.invoke(Invocation.java:220)
        at com.hazelcast.spi.impl.operationservice.impl.InvocationBuilderImpl.invoke(InvocationBuilderImpl.java:60)
        at com.hazelcast.client.impl.protocol.task.AbstractPartitionMessageTask.processMessage(AbstractPartitionMessageTask.java:67)
        at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.initializeAndProcessMessage(AbstractMessageTask.java:123)
        at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.doRun(AbstractMessageTask.java:111)
        at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.run(AbstractMessageTask.java:101)
        at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:161)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:159)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:127)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.run(OperationThread.java:110)
Caused by: java.lang.IllegalArgumentException: There is no suitable accessor for 'eventType' on class 'java.lang.Long'
        at com.hazelcast.query.impl.getters.ReflectionHelper.createGetter(ReflectionHelper.java:168)
        ... 35 more

从异常中我了解到 Hazelcast 正在尝试在 IMapValue 字段上应用索引。

有没有办法在 IMapKey 字段上放置索引?

尝试

        <indexes>
            <index ordered="true">__key.eventType</index>
        </indexes>

作为 key-value 商店,通常搜索值,这就是索引所期望的。当您将 eventType 放入索引中时,它会在 价值。您需要将其更改为 __key.eventType 以使其在密钥中显示。

如果您需要频繁搜索访问复合主键的一部分,作为索引实现,那么主键结构的选择可能需要重新审视。

此外,如果可以,请从 3.11.2 升级到 3.12.1。幕后有一些查询改进。