Кэш второго уровня NHibernate: кеш запросов не работает должным образом - PullRequest
0 голосов
/ 08 января 2019

Пакеты, которые я использую:

NHibernate 5.2.1
NHibernate.Caches.SysCache 5.5.1

Конфигурация NH кеша:

<configuration>
    <configSections>
        <section name="syscache" type="NHibernate.Caches.SysCache.SysCacheSectionHandler,NHibernate.Caches.SysCache" />
    </configSections>

    <syscache>
        <!-- 3.600s = 1h; priority 3 == normal cost of expiration -->
        <cache region="GeoLocation" expiration="3600" sliding="true" priority="3" />
    </syscache>
</configuration>

Я хочу запросить несколько мест, используя их уникальные первичные ключи. В этом модульном тесте я имитирую два запроса, используя разные сеансы, но одну и ту же фабрику сеансов:

[TestMethod]
public void UnitTest()
{
    var sessionProvider = GetSessionProvider();

    using (var session = sessionProvider.GetSession())
    {
        var locations = session
            .QueryOver<GeoLocation>().Where(x => x.LocationId.IsIn(new[] {147643, 39020, 172262}))
            .Cacheable()
            .CacheRegion("GeoLocation")
            .List();

        Assert.AreEqual(3, locations.Count);
    }

    Thread.Sleep(1000);

    using (var session = sessionProvider.GetSession())
    {
        var locations = session
            .QueryOver<GeoLocation>().Where(x => x.LocationId.IsIn(new[] { 39020, 172262 }))
            .Cacheable()
            .CacheRegion("GeoLocation")
            .List();

        Assert.AreEqual(2, locations.Count);
    }
}

Если идентичные идентификаторы запрашиваются в том же порядке, второй вызов извлечет объекты из кэша. В этом примере, однако, запрос вызывается только с двумя из ранее представленных идентификаторов. Хотя местоположения были кэшированы, второй запрос извлечет их из БД.

Я ожидал, что кеш будет работать как таблица, которая запрашивается первой. Только идентификаторы, которые еще не были кэшированы, должны вызывать вызов БД. Но очевидно, что весь запрос является хеш-ключом для кэшированных объектов.

Есть ли способ изменить это поведение?

1 Ответ

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

Нет понятия о частичном кеше запросов, это все или ничего: если найдены результаты этого точного запроса - они используются, в противном случае база данных запрашивается. Это связано с тем, что система кэширования запросов не обладает конкретными знаниями о значении запросов (например, она не может вывести факт, что результат конкретного запроса является подмножеством некоторого кэшированного результата).

Другими словами, кеш запросов в NHibernate действует как хранилище документов, а не как хранилище таблиц отношений. Ключ для документа представляет собой комбинацию SQL запроса (в случае linq некоторое текстовое представление дерева выражений), всех типов параметров и всех значений параметров.

Чтобы решить ваш конкретный случай, я бы предложил провести тестирование производительности. В зависимости от тестов и размера набора данных существуют некоторые возможные решения: фильтровать кэшированные результаты на клиенте (что-то вроде следующего), или не использовать кэш запросов, или вы можете реализовать некоторый механизм кэширования для конкретного запроса на уровне приложения.

[TestMethod]
public void UnitTest()
{
    var sessionProvider = GetSessionProvider();

    using (var session = sessionProvider.GetSession())
    {
        var locations = session
            .QueryOver<GeoLocation>()
            .Cacheable()
            .CacheRegion("GeoLocation")
            .List()
            .Where(x => new[] {147643, 39020, 172262}.Contains(x.LocationId))
            .ToList();

        Assert.AreEqual(3, locations.Count);
    }

    Thread.Sleep(1000);

    using (var session = sessionProvider.GetSession())
    {
        var locations = session
            .QueryOver<GeoLocation>().
            .Cacheable()
            .CacheRegion("GeoLocation")
            .List()
            .Where(x => new[] {39020, 172262}.Contains(x.LocationId))
            .ToList();

        Assert.AreEqual(2, locations.Count);
    }
}

Дополнительную информацию о том, как работает (N) кеш запросов Hibernate, можно найти здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...