Быстрое чтение таблицы базы данных Nexus

#delphi #nexusdb

#delphi #nexusdb

Вопрос:

Я хочу прочитать все содержимое таблицы в память как можно быстрее. Я использую базу данных Nexus, но я мог бы использовать некоторые методы, которые применимы ко всем типам баз данных в Delphi.

Таблица, которую я просматриваю, содержит 60 000 записей с 20 столбцами. Итак, не такой уж большой набор данных.

Из моего профилирования я пока обнаружил следующее:

  • Прямой доступ к таблицам с помощью TnxTable осуществляется не быстрее и не медленнее, чем с помощью SQL-запроса и ‘SELECT * FROM TableName’

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

Производительность, которую я получаю, равна

  • Перебор всех записей занимает 3,5 секунды
  • Перебор всех записей, чтение значений и их сохранение занимает 3,7 секунды (т.е. всего на 0,2 секунды больше)

Пример моего кода

 var query:TnxQuery;
begin
    query.SQL.Text:='SELECT * FROM TableName';
    query.Active:=True;

    while not query.Eof do
        query.Next;
  

Это занимает 3,5 секунды для таблицы с 60 000 строками.

Звучит ли такая производительность разумно? Могу ли я воспользоваться другими подходами, которые позволили бы мне быстрее считывать данные?

В настоящее время я считываю данные с сервера на том же компьютере, но в конечном итоге это может быть с другого сервера в локальной сети.

Комментарии:

1. Это само по себе занимает 3,5 с или у вас есть другие инструкции в цикле? Потому что, если вы читаете данные, вы, вероятно, делаете это с помощью FieldByName, который известен тем, что он не такой быстрый

Ответ №1:

Вы должны использовать режим BlockRead с TnxTable для оптимальной скорости чтения:

 nxTable.BlockReadOptions := [gboBlobs, gboBookmarks];
//leave out gboBlobs if you want to access blobs only as needed
//leave out gboBookmarks if no bookmark support is required

nxTable.BlockReadSize := 1024*1024; //1MB
// setting block read size performs an implicit First
// while block read mode is active only calls to Next and First are allowed for navigation
try
  while not nxTable.Eof do begin
    // do something....
    nxTable.Next;
  end;
finally
  nxTable.BlockReadSize := 0;
end;
  

Кроме того, если вам не нужно устанавливать диапазон для определенного индекса, обязательно используйте индекс последовательного доступа для максимально быстрого доступа.

Комментарии:

1. ВАУ. Общее время теперь сокращено с 3,7 секунды до 0,5 секунды. Совсем неплохо.

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

3. До тех пор, пока вы сохраняете SAI помеченным как значение по умолчанию, а свойство IndexName пустым, тогда да, SAI будет использоваться.

4. Похоже, что этот же метод работает и с TnxQuery. Я получаю ту же производительность, используя ‘SELECT * FROM TABLENAME’, что и при использовании TnxTable.

5. Режим BlockRead работает с TnxQuery, да. Но производительность зависит от того, используете ли вы оперативный набор результатов или нет. При действительном наборе результатов выполнение запроса вернет курсор прямой таблицы, который идентичен курсору, используемому в TnxTable. Но если текущий результирующий набор отключен (или вы делаете свой запрос слишком сложным для текущего результирующего набора), то движок sql должен создать таблицу в памяти и скопировать в нее все соответствующие записи. Вы по-прежнему получите преимущество в производительности от режима BlockRead при чтении из результирующего набора, но создание этого результирующего набора займет больше времени.