2009-06-22 3 views
4

Я строю запрос MySql, который пакет вставляет 4096 записей одновременно. Фактическая вставка довольно быстрая, но узкое место генерирует запрос. Любые подсказки по оптимизации этого? Генерация строк в настоящее время занимает примерно 18 раз дольше, чем запрос.Оптимизация конкатенации строк F #

    let builder = StringBuilder(524288) 
        Printf.bprintf builder 
         " 
         INSERT INTO %s 
          (`ID`, 
           `Tag`, 
           `Port`, 
           `Excess`, 
           `Return`, 
           `StartDate`, 
           `EndDate` 
          ) 
          values " 
         x.evaluationstable 

        evaluations 
        |> Seq.iter(fun (e) -> 
         Printf.bprintf builder 
          " (%d, '%s', '%s', %A, %A, %A, %A), " 
          e.ID 
          e.Tag 
          e.Port 
          e.Excess 
          e.Return 
          (e.StartDate.ToString(x.datetimeformat)) 
          (e.EndDate.ToString(x.datetimeformat)) 
        ) 

ответ

10

Попробуйте использовать StringBuilder.AppendFormat вместо Printf.bprintf. Когда я сделал это изменение в моем примере вашего вопроса, я увидел огромное увеличение производительности (~ 80x).

evaluations 
|> Seq.iter (fun (e) -> 
    builder.AppendFormat(
     " ({0}, '{1}', '{2}', {3}, {4}, {5}, {6}), ", 
     e.ID, 
     e.Tag, 
     e.Port, 
     e.Excess, 
     e.Return, 
     (e.StartDate.ToString("MM/dd/yyyy")), 
     (e.EndDate.ToString("MM/dd/yyyy")) 
    ) |> ignore 
) 
+0

Ницца. Это работало очень хорошо, я вижу около 10-кратного увеличения скорости, но это включает открытие соединения и выполнение запроса. Благодаря! – MikeW

3

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

Если вы все еще можете сделать это в пакете, а не в нескольких отдельных вызовах только в рамках одной транзакции, я не уверен.

+0

Благодарим за отзыв. Я изначально преобразовал это из набора параметризованных операторов и получил огромное увеличение уровня с помощью прямой многострочной вставки. Я мог бы попробовать гибрид двух, гораздо большего многорядного параметризованного типа. Я довольно новичок в F #, поэтому мне было интересно, есть ли более эффективный способ выполнения строки concat, которую я пытаюсь здесь. Я обнаружил, что формат% A невероятно дорог и ему удалось почти вдвое сократить время выполнения, не используя их. – MikeW

+0

Безопаснее, да. Более эффективный, нет! Накладные расходы на округление до db для каждого заявления будут убивать производительность. –

+2

@Robert: Это был вопрос об использовании пакета, а не нескольких отдельных вызовов. Предполагая, что вы можете, * не будет * быть дополнительным круглым отключением. –

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