Как поместить больше чем 1 000 значений в Oracle В пункте [дубликат]

Неустранимая ошибка: допустимый размер памяти из XXX байт исчерпан (пытался выделить XXX байты)

Недостаточно памяти для запуска вашего скрипта. PHP достиг предела памяти и перестает его выполнять. Эта ошибка является фатальной, сценарий останавливается. Значение предела памяти можно настроить либо в файле php.ini, либо с помощью ini_set('memory_limit', '128 M'); в скрипте (который перезапишет значение, определенное в php.ini). Цель ограничения памяти заключается в том, чтобы не допустить, чтобы один скрипт PHP собирал всю доступную память и приводил к остановке всего веб-сервера.

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

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

Вопросы, относящиеся:

96
задан Aaron Palmer 4 September 2013 в 15:38
поделиться

6 ответов

Поместите значения во временную таблицу и затем сделайте выбор, где идентификатор в (выбирают идентификатор из поддающегося соблазну)

89
ответ дан Otávio Décio 24 November 2019 в 05:33
поделиться

Я почти уверен, что можно разделить значения через несколько использование INS ИЛИ:

select * from table1 where ID in (1,2,3,4,...,1000) or 
ID in (1001,1002,...,2000)
54
ответ дан Peter Severin 24 November 2019 в 05:33
поделиться

Можно попытаться использовать следующую форму:

select * from table1 where ID in (1,2,3,4,...,1000)
union all
select * from table1 where ID in (1001,1002,...)
46
ответ дан Andreas Petersson 24 November 2019 в 05:33
поделиться

Где Вы получаете список идентификаторов от во-первых? Так как они - идентификаторы в Вашей базе данных, они происходили из некоторого предыдущего запроса?

, Когда я видел это в прошлом, это был because:-

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

я думаю, что могут быть лучшие способы переделать этот код что, просто заставив этот SQL-оператор работать. Если Вы предоставляете больше подробную информацию, Вы могли бы получить некоторое представление.

8
ответ дан WW. 24 November 2019 в 05:33
поделиться

Используйте... от таблицы (...:

create or replace type numbertype
as object
(nr number(20,10) )
/ 

create or replace type number_table
as table of numbertype
/ 

create or replace procedure tableselect
( p_numbers in number_table
, p_ref_result out sys_refcursor)
is
begin
  open p_ref_result for
    select *
    from employees , (select /*+ cardinality(tab 10) */ tab.nr from table(p_numbers) tab) tbnrs 
    where id = tbnrs.nr; 
end; 
/ 

Это - один из редких случаев, где Вам нужна подсказка, еще Oracle не будет использовать индекс на идентификаторе столбца. Одно из преимуществ этого подхода - то, что Oracle не должна трудно анализировать запрос снова и снова. Используя временную таблицу большинство времен медленнее.

редактирование 1 упростило процедуру (благодаря jimmyorr) + пример

create or replace procedure tableselect
( p_numbers in number_table
, p_ref_result out sys_refcursor)
is
begin
  open p_ref_result for
    select /*+ cardinality(tab 10) */ emp.*
    from  employees emp
    ,     table(p_numbers) tab
    where tab.nr = id;
end;
/

Пример:

set serveroutput on 

create table employees ( id number(10),name varchar2(100));
insert into employees values (3,'Raymond');
insert into employees values (4,'Hans');
commit;

declare
  l_number number_table := number_table();
  l_sys_refcursor sys_refcursor;
  l_employee employees%rowtype;
begin
  l_number.extend;
  l_number(1) := numbertype(3);
  l_number.extend;
  l_number(2) := numbertype(4);
  tableselect(l_number, l_sys_refcursor);
  loop
    fetch l_sys_refcursor into l_employee;
    exit when l_sys_refcursor%notfound;
    dbms_output.put_line(l_employee.name);
  end loop;
  close l_sys_refcursor;
end;
/

Это произведет:

Raymond
Hans
5
ответ дан tuinstoel 24 November 2019 в 05:33
поделиться

Я тоже оказался здесь в поисках решения.

В зависимости от максимального количества элементов, которые вам нужно запросить, и при условии, что ваши элементы уникальны, вы можете разделить свой запрос на групповые запросы по 1000 элементов и вместо этого объединить результаты на своей стороне (здесь псевдокод):

//remove dupes
items = items.RemoveDuplicates();

//how to break the items into 1000 item batches        
batches = new batch list;
batch = new batch;
for (int i = 0; i < items.Count; i++)
{
    if (batch.Count == 1000)
    {
        batches.Add(batch);
        batch.Clear()
    }
    batch.Add(items[i]);
    if (i == items.Count - 1)
    {
        //add the final batch (it has < 1000 items).
        batches.Add(batch); 
    }
}

// now go query the db for each batch
results = new results;
foreach(batch in batches)
{
    results.Add(query(batch));
}

Это может быть хорошим компромиссом в сценарии, когда у вас обычно не более 1000 элементов, поскольку наличие более 1000 элементов было бы вашим крайним сценарием "высокого уровня". Например, если у вас есть 1500 элементов, два запроса (1000, 500) не будут такими уж плохими. Это также предполагает, что каждый запрос сам по себе не является особенно дорогим.

Это не было бы подходящим, если бы ваше типичное количество ожидаемых элементов должно быть намного больше - скажем, в 100000 диапазон - требуется 100 запросов. Если это так, то вам, вероятно, следует более серьезно подумать об использовании решения для глобальных временных таблиц, представленного выше, как наиболее «правильного» решения. Более того, если ваши элементы не уникальны, вам также потребуется устранить повторяющиеся результаты в ваших партиях.

4
ответ дан 24 November 2019 в 05:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: