Как найти РАЗМЕР памяти записей, возвращаемых в SQL-запросе в Oracle? - PullRequest
2 голосов
/ 25 октября 2019

Я выполняю запрос, который возвращает 10 000 записей.

SELECT * FROM employee WHERE id < 11000;

Возвращенные данные состоят из 85 столбцов (varchar, date, no.). (Также у меня есть другой подобный запрос, который получает данные, состоящие всего из 10 столбцов (varchar).)

Есть ли способ в Oracle, чтобы найти размер данных этого набора результатов? Как загруженные данные будут иметь размер 100 МБ или 200 МБ

Требование : На самом деле мне нужно загрузить все записи в память;для этих записей для некоторой обработки в Java. Поэтому мне нужно проверить размер данных, используя некоторые предварительные условия в Oracle или любым другим подходящим способом, которым вы можете предложить проверить то же самое? (У меня есть производственный доступ. Поэтому я проверю логику после проверки размера данных).

Эта предварительная проверка только для того, чтобы избежать исключений "Недостаточно памяти" в java.

Если я копирую целые данные и сохраняю их в файле, он показывает только 604 КБ для 10 000 записей с 8 столбцами. Будет ли то же самое в памяти?

1 Ответ

3 голосов
/ 25 октября 2019

Как правило, вы можете использовать инструментарий Java для определения потребления памяти во время выполнения. Для получения дополнительной информации об этом смотрите здесь:

Однако не всегда так просто определить реальное потребление памяти по разным причинам, некоторые из которых:

  • Каркасы, библиотеки и даже JVM могут создаватькопии ваших данных или кеша и их повторное использование
  • Запросы могут возвращать результаты разного размера, особенно при использовании типов столбцов переменной длины, таких как VARCHAR. Вам нужно прочитать эти данные, чтобы определить фактический размер соответствующих объектов
  • На некоторые объекты могут ссылаться несколько других, поэтому их размер может быть указан неправильно (например, если используется некоторая константа перечисления, которая может быть подсчитана)в размер объекта, но на самом деле это не увеличит увеличение, потому что, скорее всего, оно уже загружено).

Кроме того, в большинстве бизнес-приложений вам не нужно определять точную памятьпотребление части кода приводит к. Опять же, существуют различные причины, например:

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

Это не означает, что вы не должны думать об использовании памяти, например, вам действительно нужны все эти 10k строк в памяти одновременно? Как долго вам нужны эти данные и что вы с ними делаете?

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

Для этого вам понадобятся некоторые знания о том, что будут содержать ваши строки, например, целые числа Integer, Long или BigInteger экземпляров или сколько столбцов может быть. Кроме того, вам необходимо знать как минимум требования к памяти для типов данных, то есть мы не учитываем кэширование, дублирование, накладные расходы для ResultSet и т. П.

Размеры для объектов Javaзависит от различных вещей, например, какой JVM вы используете, будь то 32- или 64-битная JVM и т. д. Различные источники утверждают, что потребление памяти объектом может быть рассчитано из заголовка объекта (который часто указывается как 12 байт). в размере) и размер полей объекта.

Используя это, мы предположим, что Integer будет иметь размер 16 байтов (12b заголовок и 4b int), Date будет 24 байта(Заголовок 12b, 8b fastTime и ссылка 4b cdate), String будет заголовком 12b, ссылкой 4b char [], другими полями 8b, заголовком 12h char [] и байтами длины 2 * для самих символов (или 36 +2 * длина всего).

Итак, скажем, ваши 85 столбцов разделены на 20 целых чисел, 10 дат и 55 строк максимальной длины 256 байт. Для одной строки потребуется не менее 20 * 16 + 10 * 24 + 55 * 548 = 30700 байт. Таким образом, для строк размером 10 тыс. Потребуется 307000000 байт или примерно 300 МБ (когда все строки имеют максимальную длину).

Если я скопирую все данные и сохраню их в файле, будет показано только 604 КБ для 10 000 записей, имеющих 8столбцы.

Давайте немного разберемся с этим:

  • 604 КБ будет 618496 байт (1024 - один КБ)
  • Разделите это на10 Кбайт, и вы получите в среднем 61,8 байт на строку
  • Разбейте на 8, и вы получите 7,7 байт на столбец (если мы не примем во внимание какие-либо разделители строк или столбцов)
  • Давайте округлим его до 8 байт на столбец и предположим, что ваш текстовый файл имеет кодировку Latin-1 (так, 1 байт на символ), поэтому каждый текстовый столбец имеет в среднем 8 символов, что довольно мало

В более простом вычислении, если мы будем использовать те же предположения, что и выше, 604 КБ будет означать, что ваши данные будут состоять примерно из 604 КБ символов, что в Java потребовало бы 1208 КБ (или около 1,2 МБ) только для одних только символьных данных. Добавьте к этому издержки для строк 80 КБ, то есть 36 байтов * 80 КБ, что примерно на 2,8 МБ больше, так что для данных потребуется около 4 МБ в памяти.

...