2013-09-28 1 views
4

Я прототипировал подход к интеграции Lucene.NET с SQL Server с использованием SQL Server FileTable. Использование очень удобно, и код прост - мне не нужно ничего особенного настраивать Lucene.NET. Преимущество, которое я ищу, в основном работает и enterpriseisey - моя компания управляет SQL Server 24/7, и сохранение индекса поиска в одном и том же контрольном пространстве имеет для нас много преимуществ (... и я понимаю, что не получу точных транзакционных согласованность, это нормально).SQL Server 2012 FileTable Медленная производительность при создании файла (интеграция Lucene.NET)

Проблема: независимо от того, что я делаю, при записи в файл в общей папке UNC FileTable UNC с использованием WinAPI (через System.IO.FileStream) накладывается примерно 200 миллисекунд (+ - 20-30 мс) , Это важно для Lucene.NET, потому что операция записи индекса непосредственно в мою локальную файловую систему занимает ~ 50 мс, тогда как одна и та же операция с FileTable занимает 2-3 секунды!

Чтобы убедиться в этом, я создал еще один эксперимент, который пишет 3 новых (создания) файлов с 10 КБ, 1 МБ и 10 МБ. Я написал эти 3 файлов:

  1. Локальный каталог (c:\Search\\)
  2. Не-FileTable доли через пути UNC (\\\127.0.0.1\\Search\\)
  3. FileTable UNC путь (\\\127.0.0.1\[instance-share]\\search_index\\)

Использование System.Diagnostics.Stopwatch, запись в локальный каталог была максимально быстрой, как и ожидалось, запись в не-FileTable-ресурс была медленнее, но сопоставима, а FileTable был на порядок медленнее. Интересно, что 2 больших размера файлов выполняются аналогично в случае 2 и 3, что заставляет меня поверить в накладные расходы, когда уровни создания файлов устанавливаются таймингами.

Вопрос: Кто-нибудь имеет более глубокое понимание того, почему создание файла с помощью FileTable настолько «медленное»?

Это виртуальная машина разработки с небольшой параллельной активностью (4 ГБ ОЗУ, 2 vCPU, вероятно, некоторые конкуренты IO, но эти тесты предназначены для относительных сравнений). Вставка в SQL Server для тривиальной строки на этом поле едва достигает 1 мс.

У меня нет удобного кода, но скоро опубликует с редактированием (с точными таймингами) - это очень просто и просто записывает 4K кусков статически инициализированного массива байтов в цикле до нужного размера.

я выполнить следующие рекомендации, а также настроен стек SMB, без разницы в производительности: http://blogs.msdn.com/b/blogdoezequiel/archive/2011/02/11/best-practices-on-filestream-implementations.aspx#.UkbEYtKshcZ

EDIT: Задержки из выходного тестового консоли:

Writing files for directory: c:\Search 
     Writing file size : 10240 
     Writing file size : 1048576 
     Writing file size : 10485760 
Writing files for directory: \\127.0.0.1\Search 
     Writing file size : 10240 
     Writing file size : 1048576 
     Writing file size : 10485760 
Writing files for directory: \\127.0.0.1\Sql2012\FIndex\search_index 
     Writing file size : 10240 
     Writing file size : 1048576 
     Writing file size : 10485760 

Write Timings 
--------------------------------------------------------------- 
Paths (rows): Local, Shared, SQL File Table 
Sizes (columns): 10KB, 1MB, 10MB 
--------------------------------------------------------------- 
Local: 3      2      17 
Share: 28      31      64 
FTable: 205      249      317 

Исходный код (очень прост, размещен для полноты): Консоль Главная с ASCII арт опущена:

private static readonly string[] paths = new string[] 
{ 
    @"c:\Search", 
    @"\\127.0.0.1\Search", 
    @"\\127.0.0.1\Sql2012\FIndex\search_index" 
}; 

private static readonly int[] sizes = new int[] 
{ 
    1024 * 10, 
    1024 * 1024, 
    1024 * 1024 * 10 
}; 

static void Main(string[] args) 
{ 
    // Directory: Size 1, 2, 3 
    var timings = new long[3, 3]; 
    var stopwatch = new Stopwatch(); 
    for(var x = 0; x < 3; x++) 
    { 
     Console.WriteLine("Writing files for directory: {0}", paths[x]); 
     for(var y = 0; y < 3; y++) 
     { 
      Console.WriteLine("\tWriting file size : {0}", sizes[y]); 
      string fileName = Path.Combine(paths[x], Guid.NewGuid().ToString() + ".bin"); 
      stopwatch.Start(); 
      FileIOTestHelper.WriteFile(fileName, sizes[y]); 
      stopwatch.Stop(); 
      timings[x, y] = stopwatch.ElapsedMilliseconds; 
      stopwatch.Reset(); 
     } 
    } 

// ascii art display code 
} 
Класс

Реализации:

public static class FileIOTestHelper 
{ 
    private static readonly byte[] testBuffer = CreateBuffer(); 

    private static byte[] CreateBuffer() 
    { 
     var buffer = new byte[4096]; 
     for (var i = 0; i < 4096; i++) 
     { 
      buffer[i] = (byte)(i % 256); 
     } 

     ForceIOJit(buffer); 
     return buffer; 
    } 

    private static void ForceIOJit(byte[] initBuffer) 
    { 
     // Shouldn't matter, but eliminating any possible warm up cost. 
     using (var fs = new FileStream(Path.GetTempFileName(), FileMode.Open)) 
     { 
      fs.Write(initBuffer, 0, 4096); 
      fs.Flush(); 
     } 
    } 

    public static void WriteFile(string name, int sizeInBytes) 
    { 
     var count = sizeInBytes/4096; 
     var remainder = sizeInBytes % 4096; 
     using (var fs = new FileStream(name, FileMode.Create)) 
     { 
      for (int i = 0; i < count; i++) 
      { 
       fs.Write(testBuffer, 0, 4096); 
      } 

      if (remainder > 0) 
      { 
       fs.Write(testBuffer, 0, remainder); 
      } 

      fs.Flush(); 
     } 
    } 
} 
+0

Мой помощник, который является консультантом по MCS и хорошо знает SQL Server, провел некоторые эксперименты по этой проблеме и обнаружил, что производительность FileTable чувствительна к размеру буфера FileStream. Кажется, он работает лучше всего на 64 КБ. Я отправлю редактирование с подробной информацией. – bkrakower

ответ

2

После намного больше испытаний, латентность я испытываю последовательна и не чувствителен к размеру буфера. Я принимаю это как ограничение FileTable, и он менее идеален для очень многопоточного ввода-вывода.

+0

Любые обновления по этому вопросу? Просто любопытно. – camainc

+0

Нет, ничего на этом фронте. Использование Elasticsearch:>. – bkrakower