Почему SQLyog возвращает результаты запросов MySQL в 10 раз быстрее, чем моя Delphi-программа? - PullRequest
2 голосов
/ 23 июня 2009
select rectype,jobid,jobrecid,template,assignedto,entereddt,enteredby,ref1,processed,processeddt,
processbydt,title,description,connectlanhandle,finished,updateddt,ref2,cancelled,
requireaccept,acceptrejectstate,acceptrejectbydt,alert1dt,alert2dt,alert3dt,despatchallowed,
flag,ref3,projectid,duration,skillset,postcode,prefschedulefrom,prefscheduleto,customdata1,
customdata2,customdata3,hasnotes,displayjobtype,createdby,createddt,colour
 from jobs
 where updateddt >= '1982-02-05 17:25:38'
 or (processed = 'N' and
     cancelled = 'N')
 order by jobid, jobrecid

Этот запрос возвращает ~ 80000 результатов. SQLyog (графический интерфейс MySQL) может возвращать результаты в видимой сетке за ~ 600 мс. Моя программа Delphi, которая подключается с использованием ODBC (последние версии драйверов MyODBC), для выполнения запроса требуется ~ 6000 мс, даже не начав просматривать результаты.

Какие-нибудь идеи о том, что я могу сделать, чтобы ускорить мою программу?

Ответы [ 7 ]

6 голосов
/ 23 июня 2009

Я предполагаю, что SQLyog на самом деле не отображал все 80 000 результатов за 600 мс - он все еще может загружать более поздние, пока отображает первые. (В частности, большинство каркасов GUI, которые я видел, не могут заполнить 80 000 строк так быстро даже без участия базы данных.)

Вы можете попытаться сделать то же самое, если предположить, что используемый вами API позволяет вам получать результаты потоковым способом (вместо того, чтобы передавать все в память до возврата вызова).

5 голосов
/ 23 июня 2009

Я попробовал это самостоятельно на основной таблице (без объединения) и обнаружил, что даже если вы нажмете кнопку «Показать все», SQLyog не сразу выведет все результаты на сетку, попробуйте сами, переместив кнопку прокрутки в самая низкая область, вы заметите, что sqlyog замедлится на несколько мгновений и принесет больше результатов.

также известно, что ODBC медленнее, поскольку добавляет дополнительный слой к собственному доступу, поэтому попробуйте использовать MyDac из DevArt , который использует прямой доступ к mysql (даже без клиентской библиотеки mysql).

и как больше всего сказано, никогда не пытайтесь показать пользователю 80 000 записей за один раз.

Кстати, официальные инструменты MySql с графическим интерфейсом от солнца, построенные с использованием Delphi; -)

2 голосов
/ 23 июня 2009

Как уже говорили другие, это вероятно потому, что SQLyog не загружает все записи и, вероятно, ограничивает его до 200 или около того.

Чтобы решить эту проблему с производительностью, вы можете использовать хитрые уловки. Так как вы в основном загружаете кеш набора данных в свое приложение при запуске, вы можете сделать это. Загрузка все равно займет 6 или 8 секунд, но ваше приложение все равно запустится, и пользовательский интерфейс будет пригоден для использования. Если кто-то сделал что-то, что требовало кеша до того, как он был загружен, вы могли бы просто отобразить курсор песочных часов или сообщение с надписью «пожалуйста, один момент ...», пока кеш не был готов.

При обращении к данным в потоке следует помнить, что обычно вам необходимо создать отдельное соединение с базой данных в потоке. Как то так:

type
  TLoadCacheThread = class(TThread)
  private
    FConnection : TODBCConnection; // Or whatever, I don't use ODBC :-)
    FQuery : TODBCQuery;
    FMemData : TkbmMemTable; // This is what I use, YMMV
  protected
    procedure PopulateCachedDataset;
  public
    constructor Create; override;
    procedure Execute; override;
  end;

constructor Create;
begin
  inherited Create(True); // create suspended thread
  FConnection := TODBCConnection.Create(nil);
  // Set any properties for the connection here.
  FQuery := TODBCQuery.Create(nil);
  // Set any properties for the query here.
  FQuery.SQL.Text := 'select * from mytable';
  Resume;
end;

procedure Execute;
begin
  FQuery.Open;
  FMemTable.LoadFromDataset(FQuery);
  Synchronize(PopulateCachedDataset);
end;

// The idea here is that you're loading into a mem dataset, which can then
// quickly be copied to another memory dataset, rather than loading the
// cached data directly from FQuery, which is slow and why we're threading
// in the first place. This assumes you have some kind of globalsettings unit
// or class, and it has a cacheddataset variable or property.
procedure PopulateCachedDataset;
begin
  GlobalSettings.CachedDataset.LoadFromDataset(FMemTable);
end;

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

НТН

2 голосов
/ 23 июня 2009

Полагаю, это связано с тем, что SQLyog использует собственный API MySQL C (прямое соединение), а вы используете коннектор ODBC. Вы пробовали сторонние разъемы, такие как MyDAC от Devart? Оттуда вы можете получить бесплатную пробную версию и протестировать ваше приложение.

FWIW Я использую MyDac уже много лет, и я действительно доволен (производительность / приз / поддержка)

1 голос
/ 23 июня 2009

Вы можете использовать LIMIT 0,1000 в запросе, а затем изменить его, когда пользователь достигнет дальнего конца - отметив событие OnAfterScroll.

0 голосов
/ 23 июня 2009

SQLyog, вероятно, не будет загружать все 80000 строк одновременно, по крайней мере, некоторые инструменты БД, которые я использую, делают "нагрузку по требованию" при прокрутке. Если вам абсолютно необходимо получить все записи одновременно, рассмотрите возможность использования потока для выполнения запроса и заполнения внутреннего массива.

0 голосов
/ 23 июня 2009

По моему мнению, вам следует подумать дважды о своей прикладной программе и / или архитектуре базы данных - это бесполезно при работе с 80К записями. Попробуйте сузить свой запрос - если вы не сделаете свою жизнь проще - никто не станет $)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...