Delphi: выполнение sql-запросов к memtable или другому типу набора данных

Я использую Firedac для создания соединения SQL Lite в локальном файле .db. Я использую:

  • TFDConnection: для создания объекта подключения
  • TFDQuery: для выполнения моих запросов SQLite.

Я хочу скопировать все данные или таблицы из моего файла базы данных SQLite в память, а затем выполнить на нем SQL-запросы.

Я читал, что могу использовать mMemTable или другие наборы данных, но вся информация об этом больше сбивает с толку, чем помогает мне.

Я хочу добиться этого, потому что мне приходится выполнять «тяжелые» запросы (тысячи запросов внутри цикла for), но без ущерба для скорости и ресурсов. В настоящее время у меня есть 5 query.open ("SELECT * ....") внутри очень большого цикла, что делает мой код очень медленным. Я полагаю, это происходит из-за многих вещей query.open ().

Если у меня есть копия данных SQLite в памяти, а затем я буду выполнять запросы к этому набору данных, это резко увеличит скорость моего кода.

Я реализовал это в другой части моего кода, где я использовал ограниченный объем данных, взятых из файла SQLite внутри отсортированных списков, а затем я перебирал свои списки. После замены query.open () внутри этого большого цикла производительность увеличилась более чем на 300%.

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

Итак, кто-нибудь может помочь мне с вышеуказанной проблемой? Может быть, небольшой и «понятный» урок по этому поводу?


Похоже, что на мой вопрос все еще нет ответа. Я постараюсь уточнить другой пример кода, чтобы разобраться в ситуации. Я все еще пытаюсь достичь того, о чем говорил выше. Я хочу скопировать данные из моей базы данных SQLite в память, ОТКЛЮЧИТЬ, а затем выполнить запросы SQLite в базе данных памяти. Предполагается работать с TFDQuery, TFDLocalSQL, TFDConnection.

Я создаю и извлекаю данные из файла SQL, используя соединение «conn» и «запрос». Затем я активирую

try
   // connection with local SQL file to fetch data from
   query.Connection := conn;
   query.Open('SELECT * FROM CAMPAIGNS');
   query.FetchAll();
   // I've put SQL text because FDQuery1 must me active and SQL text must be 
   // included
   FDQuery1.SQL.Text:='SELECT 1';
   FDQuery1.Active:= true;
   // the following line of code, is supposed to copy data and structure
   FDQuery1.CloneCursor(query,true,true);
finally
   conn.Close();
   query.Free();
   conn.Close();
end;
// it seems from showmessage that records exist inside TFDQuery
showmessage(FDQuery1.RecordCount.ToString);
// when I execute the following query, it tells that such table does not 
// exist
FDQuery1.Open('SELECT * FROM CAMPAIGNS');

Добро пожаловать в Stack Overflow. К сожалению, это не сайт для предоставления учебных материалов.

MartynA 13.09.2018 19:15

Попробуйте ускорить запросы, добавив индексы в свою базу данных SQLite. Кроме того, если у вас много циклов с запросами внутри, вы должны проверить, можете ли вы улучшить свой алгоритм, либо заменив логику внешних циклов логикой SQL, либо предварительно загрузив определенную ограниченную информацию из базы данных в хэш-таблицы или словари.

NineBerry 13.09.2018 19:18

Я произвел оптимизацию и заменил логику цикла на логику SQL, насколько это возможно, но я все же добился большей скорости. Я использую данные для записи в StringTable. Также я не могу использовать привязки (я не очень хорошо знаком с привязками и элементами управления DataAware) для такого типа таблиц, потому что я использую данные очень «индивидуальным» способом, извлекая данные из разных таблиц и выполняя много вычислений перед записью в ячейки.

Thersippos 13.09.2018 22:09

NineBerry, я прочитал более 3000 сообщений в stack overflow по широкому кругу концепций программирования и проблем. Я не прошу ответа с помощью учебника, но о том, как я могу его реализовать. Если у кого-то есть решение, опубликованное где-то еще (возможно, на другом сайте), я был бы признателен. Я просто добавил это, потому что, возможно, у кого-то уже есть ответ, но ему скучно писать его здесь снова.

Thersippos 13.09.2018 22:13

Я не думаю, что ваши комментарии на самом деле проясняют вашу проблему, по крайней мере, для меня. Где ваши данные на самом деле сохраняются и извлекаются из таблиц Sqlite в базе данных локальной файловой системы или надлежащей СУД на сервере?

MartynA 14.09.2018 00:50

Как упоминалось в моем вопросе (вначале), я использую локальный файл SQLite. Я хочу получить все данные внутри набора данных, а затем выполнить SQL-запросы к этому набору данных. Мне нужен этот «автономный режим», чтобы не читать напрямую из файла, что сокращает время выполнения.

Thersippos 14.09.2018 14:56
0
6
3 110
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы пробовали загружать данные из таблиц с помощью свойства data?

FDQuery1.Open; FDQuery1.FetchAll; FDMemTable1.Data := FDQuery1.Data;

Как я могу запускать SQL-запросы в MemTable? Даже если у меня есть данные, скопированные в набор данных, дальше я хочу выполнять запросы к нему (автономный режим).

Thersippos 14.09.2018 17:10

Используйте соединение TfdLocalSQL для создания локального «сервера базы данных», который может обслуживать вашу таблицу памяти в качестве набора данных для TfdQuery.

JacalarRick 14.09.2018 22:14

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

Thersippos 27.09.2018 15:44
Ответ принят как подходящий

Случай слепого, ведущего слепого, я все еще пытаюсь понять это сам, но я думаю, вам нужно использовать TFDLocalSQL в качестве связующего звена между TFDMemTable и TFDQuery. Для получения дополнительной информации попробуйте http://docwiki.embarcadero.com/RADStudio/Rio/en/Local_SQL_(FireDAC)

Другие вопросы по теме