2015-11-24 5 views
0

Спасибо за чтение!C# Oracle SQL Connection чрезвычайно медленна на больших наборах данных

Я столкнулся с проблемой, когда мое соединение с Oracle (2,5 миллиона записей) начинается с «относительно быстрого», а затем значительно замедляется.

Вот как я создаю соединение: (Это синхронизация между двумя базами данных, моя локальная БД может быть Oracle/SQL Server/MySQL - кто знает?)

private static void ImportSomeData(string sql, DbConnection connection, int batchSize) 
{ 
     var command = connection.CreateCommand(); 
     command.CommandText = sql; 
     //Throw an exception here if needed 
     var results = command.ExecuteReader(); 

     if (results.HasRows) 
     { 
      //...read here. 
     } 
} 

Размер партии относится в EntityFramework я поддерживаю соединение для ~ 200 строк, а затем воссоздаю (ошибки OutOfMemory вполне возможны, и я просто пытаюсь понять, каков наш оптимальный размер. (Следует отметить, что я использовал 200-20000 как размер партии до воссоздания IRepository и, похоже, он имеет очень небольшой эффект, кроме ошибок памяти в верхнем размере).

пример бревен:

[INFO] [2015-11-24 12:34:21] Imported 1000 Clients 
[INFO] [2015-11-24 12:34:24] Imported 2000 Clients 
[INFO] [2015-11-24 12:34:26] Imported 3000 Clients 
[INFO] [2015-11-24 12:34:29] Imported 4000 Clients 
[INFO] [2015-11-24 12:34:33] Imported 5000 Clients 
[INFO] [2015-11-24 12:34:37] Imported 6000 Clients 
[INFO] [2015-11-24 12:34:41] Imported 7000 Clients 
[INFO] [2015-11-24 12:34:45] Imported 8000 Clients 
[INFO] [2015-11-24 12:34:49] Imported 9000 Clients 
[INFO] [2015-11-24 12:34:55] Imported 10000 Clients 
[INFO] [2015-11-24 12:35:00] Imported 11000 Clients 
[INFO] [2015-11-24 12:35:05] Imported 12000 Clients 
[INFO] [2015-11-24 12:35:11] Imported 13000 Clients 
[INFO] [2015-11-24 12:35:17] Imported 14000 Clients 
[INFO] [2015-11-24 12:35:23] Imported 15000 Clients 
[INFO] [2015-11-24 12:35:30] Imported 16000 Clients 
[INFO] [2015-11-24 12:35:37] Imported 17000 Clients 
[INFO] [2015-11-24 12:35:44] Imported 18000 Clients 
[INFO] [2015-11-24 12:35:51] Imported 19000 Clients 
[INFO] [2015-11-24 12:35:59] Imported 20000 Clients 
[INFO] [2015-11-24 12:36:06] Imported 21000 Clients 
[INFO] [2015-11-24 12:36:14] Imported 22000 Clients 
[INFO] [2015-11-24 12:36:21] Imported 23000 Clients 
[INFO] [2015-11-24 12:36:31] Imported 24000 Clients 
[INFO] [2015-11-24 12:36:42] Imported 25000 Clients 

Я вижу это поведение на трех разных системах. Если вы посмотрите внимательно на отметки времени, вы увидите, что по мере того, как мы все дальше и дальше продвигаемся в набор результатов, время обработки 1000 строк начинает быстро закрадываться и, похоже, не выравнивается. Очевидно, есть много мест, чтобы начать устранение неполадок (и это может быть не Oracle), но мне интересно, может ли быть лучший подход к этому (через таблицу курсора/temp, index ... действительно я открыт для ничего здесь).

--Example from the server: 
[INFO] [2015-11-20 11:09:18] Imported 1000 Clients 
[INFO] [2015-11-20 11:10:45] Imported 2000 Clients 
... 
[INFO] [2015-11-20 18:06:45] Imported 508000 Clients 
[INFO] [2015-11-20 18:08:36] Imported 509000 Clients 

Любые мысли об этом будут оценены. Я видел ситуацию, когда локальное соединение в целевом приложении виновато, но я вижу такое же поведение по сравнению с наборами результатов, у которых уже есть записи в базе данных (начиная быстро и замедляясь после первоначального нажатия), поэтому я ' Интересно, есть ли лучший способ потянуть эту запись за счет сравнения.

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

EDIT Некоторые SQL просили, вот (не реальный) пример это благодаря NDA:

SELECT 
    a.A AS Field1, 
    a.B AS Field2, 
    CASE a.C 
    WHEN 'StringNum2' THEN 1 
    WHEN 'StringNum2' THEN 2 
    ... 
    ELSE -1 AS Field3, 
    --Another case statement 
    a.D AS Field9 
    ... 
    a.G AS Field10 
FROM 
    ImportTableNoJoins a 
+1

Похоже DBA выпуск .. у вас есть «DBA on Staff», это может быть по ряду причин: «Сеть медленная, вплоть до« Bad Indexes »... может ли кто-то запустить профилировщик или план затрат ..? – MethodMan

+0

Это не похоже на проблему с базой данных Oracle. Я не думаю, что когда-либо видел запрос, когда время для каждой строки становится медленнее.Вы можете это исключить, опубликовав план объяснения - найдите SQL_ID с помощью 'select * from gv $ sql, где lower (sql_text), например '% importtablenojoins%';', затем используйте его в 'select * from table (dbms_xplan.display_cursor (sql_id => '$ SQL_ID')); '. –

+0

@JonHeller Спасибо за подсказку. Я согласен, что это не похоже на поведение, которое я когда-либо видел из Oracle (или SQL Server). –

ответ

1

вы заметили ли каких-либо улучшений, если обеспечить Dispose называется?

private static void ImportSomeData(string sql, DbConnection connection, int batchSize) 
{ 
    using(var command = connection.CreateCommand()) 
    { 
     command.CommandText = sql; 
     //Throw an exception here if needed 
     var results = command.ExecuteReader(); 

     if (results.HasRows) 
     { 
      //...read here. 
     } 
    } 
} 

Кроме того, не могли бы вы показать нам текст команды SQL, который вы используете? Вот некоторые идеи по оптимизации SQL запросов: http://www.codeproject.com/Articles/55505/SQL-Query-Optimization-FAQ-Part-With-video-expla

Как хорошо, вы можете попробовать использовать счетчики производительности, чтобы определить проблемы в C# код или какой-то инструмент для профилирования базы данных Oracle: http://www.codeproject.com/Articles/42001/NET-Best-Practice-No-Using-performance-counters

+0

Спасибо за идеи. Я заметил крайне незначительное улучшение (1-3%), когда Dispose вызывается каждые ~ 200 или около того строк, поэтому есть возможность перечислить «List». Я отредактировал свой ответ, чтобы показать пример SQL, но он защищен нераскрытием, поэтому мне нужно было немного запутать его. –

Смежные вопросы