Следующий запрос, сгенерированный спящим режимом, занимает более 13 секунд и блокирует таблицу:
SELECT COUNT(auditentit0_.audit_id) AS col_0_0_ FROM Audit auditentit0_ WHERE 1=1;
Растущая таблица базы данных сервера Microsoft SQL содержит более 90 миллионов строк.
Для сервера Microsoft SQL я нашел точный способ очень быстрого получения той же информации с помощью метаданных.
Однако я бы предпочел не писать собственный код для Microsoft sql server и oracle (следующей базы данных), если в hibernate есть способ получить эту информацию.
Вот пример запроса метаданных для Microsoft sql server, который является точным и почти мгновенным:
SELECT SUM (row_count) FROM sys.dm_db_partition_stats WHERE object_id=OBJECT_ID('huge_audit_table') AND (index_id=0 or index_id=1);
Есть ли способ заставить спящий режим выдавать аналогичный запрос для количества строк таблицы?
Один опубликованный ответ показал, что представление может быть полезно. Я изучаю этот пост, чтобы узнать, может ли он решить проблему:
https://vladmihalcea.com/map-jpa-entity-to-view-or-sql-query-with-hibernate/
Зачем тебе это? результат статистики. никогда не будет точным. Но практически никакое количество строк таблицы не может быть точным - по крайней мере, в Oracle. Чтение всегда неблокирующее, поэтому количество строк может измениться во время чтения.
@ ibre5041 он блокирует. Взгляните здесь для получения дополнительной информации: sqlperformance.com/2014/10/t-sql-queries/…
@Kousalik Да, блокирует. Взгляните сюда: sqlperformance.com/2014/10/t-sql-queries/…. Приведенный мной пример запроса метаданных является точным. Напомним, что мы говорим о 90+ миллионах строк, это занимает более 14 секунд при использовании высокопроизводительной системы, и в течение этого времени таблица заблокирована. Ничего другого выполнить нельзя. Возможно, это проблема, связанная с сервером sql. Я хотел бы найти решение для гибернации.
@ D-Klotz меняет теги с Oracle11g на MSSQL
@Kousalik - это не sql-server тег Microsoft? Я хочу сохранить тег oracle, потому что это наша следующая цель. Однако, ближе к делу, я хотел бы найти решение для гибернации, которое будет работать как с сервером sql, так и с Oracle, если оно существует. Боюсь, что это не так.
счетчик выбора в Oracle не блокируется, а словари метаданных отличаются. Я не думаю, что есть такое решение. gl
@Kousalik спасибо за эту информацию. +1 вам.
не вдаваясь в детали реализации, я бы рассмотрел возможность создания собственного представления и скрытия различий РСУБД за определением представления. Затем вы можете сопоставить представление с простым объектом Hibernate. Имеет ли это смысл? Также может быть хранимая процедура.
@Kousalik Раньше я находил ссылки на просмотры. Спасибо. Я покопаюсь и посмотрю, работает ли.




В спящем режиме вы должны использовать проекции, как в предоставленной вами ссылке, чтобы гарантировать, что он работает с несколькими базами данных:
protected Long countByCriteria(DetachedCriteria criteria) {
Criteria crit = criteria.getExecutableCriteria(getSession());
crit.setProjection(Projections.rowCount());
return (Long)crit.uniqueResult();
}
Какой движок вы используете в MySQL? У меня никогда не было проблем с блокировкой количества строк в MySql или Oracle. Возможно, вам поможет следующая ссылка: Любой способ выбрать, не вызывая блокировки в MySQL?
Кроме того, после некоторого быстрого чтения я вижу, что Sql Server действительно блокируется по счетчику.
Возможно, вы могли бы использовать хранимую процедуру или какой-либо другой механизм, чтобы передать проблему в dbms.
Редактировать:
Проекции в Hibernate используются для выбора столбцов для выборки, столбцов для группировки элементов и использования встроенных агрегатных функций (sum, count, avg, max, min, countDistinct).
Это поможет вам сохранить привязку к базе данных вашего приложения. Помните, что спящий режим поддерживает около 30 баз данных.
В вашем случае у вас есть конкретная проблема с mssql, поскольку счетчик блокирует точность определения приоритетов таблицы. А использование системных представлений происходит очень быстро, поскольку вы получаете приблизительную оценку, но это нестандартно.
Вы можете инкапсулировать проблему в зависимости от представления или хранимой процедуры. Или, может быть, вы могли бы попробовать с подсказкой NOLOCK или READ UNCOMMITED в спящем режиме (в счетчике таблицы аудита это должно быть приемлемо).
Я не знаком с прогнозами, кроме быстрого гугла. Что вышеперечисленное делает для вас? Напомним, что проблема заключается в сервере microsoft sql при выполнении подсчета выбора (). Он блокирует таблицу во время сканирования (я предполагаю, индекса). Как вышеприведенная проекция обходит это? Жаль, что в спящем режиме нет чего-то особенного для count () и сервере ms sql, чтобы избежать этого.
Спасибо за информацию. NOLOCK поможет, но запрос по-прежнему занимает более 13 секунд, что недопустимо. Я изучу "представление" и посмотрю, может ли оно скрыть код, специфичный для Microsoft sql server. Если сработает, я поставлю +1 и отмечу как ответ. Спасибо.
Преимущество представления в том, что вы можете использовать другие методы, специфичные для dbms, для получения оценок количества строк. В mysql вы можете получить оценку из INFORMATION_SCHEMA или TABLE STATUS, но вам следует изучить допустимую погрешность.
Чтобы решить эту конкретную проблему, мы отступили и изменили работу пользовательского интерфейса. Благодаря совместным усилиям разработчиков UIX и пользовательского интерфейса мы договорились, что нефильтрованные запросы НЕ будут запрашивать общее количество. При начальной загрузке экрана будет отображаться только страница, полная данных. Страница 1 из 60 000 элементов управления не существует. Только когда пользователь вводит определенные критерии, в игру вступает общий счет. Эти запросы должны быть очень быстрыми. Теперь ... пользователь все еще может настроить запрос, который будет таким же серьезным, как и исходная проблема. Это должно быть исключением из нормы.
Я помню, что однажды у нас была похожая проблема, и мы то, что мы сделали, отображали что-то вроде «Page 1 - 2 - 3 - 4 - ... - 10 из многих». Не идеально, но позволяет избежать проблемы.
Чтобы решить эту конкретную проблему, мы отступили и изменили работу пользовательского интерфейса. Благодаря совместным усилиям разработчиков UIX и пользовательского интерфейса мы договорились, что нефильтрованные запросы НЕ будут запрашивать общее количество. При начальной загрузке экрана будет отображаться только страница, полная данных. Страница 1 из 60 000 элементов управления не существует. Только когда пользователь вводит определенные критерии, в игру вступает общий счет. Эти запросы должны быть очень быстрыми. Теперь ... пользователь все еще может настроить запрос, который будет таким же серьезным, как и исходная проблема. Это должно быть исключением из нормы.
Так что на ОП действительно нет однозначного ответа. Если вы столкнулись с проблемой такого типа, если у вас есть контроль над пользовательским интерфейсом и API, то пришло время переосмыслить решение. Подумайте о том, как Google обрабатывает разбиение на страницы с точки зрения пользовательского интерфейса. Дни показа "страницы 1 из (XX)" ушли в прошлое ИМХО.
1) что именно вы подразумеваете под «блокирует стол»? Я никогда раньше не видел, чтобы запрос SELECT что-либо блокировал. 2) полное сканирование таблицы выглядит неправильно, я ожидал бы быстрого сканирования индекса по столбцу PK. 3) почему ГДЕ 1 = 1? условие не обязательно. 4) это Oracle или MS SQL? 5) метаданные - это скорее оценка, чем правильное значение