簡體   English   中英

為什么SQLyog返回的MySQL查詢結果比我的Delphi程序快10倍?

[英]Why does SQLyog returns MySQL query results 10x faster than my Delphi program?

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 gui)可以在~600ms內在可見網格中返回結果。 我的Delphi程序使用ODBC(最新的MyODBC驅動程序)進行連接,只需要6000毫秒即可完成查詢,甚至無需查看結果。

關於如何使我的程序更快的任何想法?

我的猜測是SQLyog實際上並沒有在600ms內顯示所有80,000個結果 - 它可能仍在加載后者,而它顯示的是第一個。 (特別是,即使沒有涉及數據庫,我見過的大多數GUI框架都無法快速填充80,000行。)

您可以嘗試做同樣的事情,假設您正在使用的API允許您以流式方式獲得結果(而不是在調用返回之前將所有內容傳輸到內存中)。

我已經在基本表(沒有加入)上嘗試了這個,並且發現即使你點擊“全部顯示”復選框,SQLyog也不會立即將所有結果帶到網格上,通過將滾動按鈕移動到最低區域來嘗試自己你會發現sqlyog會減速一會兒,並帶來更多的結果。

也知道ODBC更慢,因為它為本機訪問添加了更多層,所以嘗試使用DevArt中的MyDac ,它使用直接訪問mysql(即使沒有mysql客戶端庫)。

而且最重要的是,永遠不要試圖一次向用戶顯示80,000條記錄。

BTW,使用Delphi構建的sun官方MySql GUI工具 ;-)

我想這是因為SQLyog使用本機MySQL C API(直接連接),而您使用的是ODBC連接器。 您是否嘗試過Devart的MyDAC等第三方連接器? 您可以從那里獲得免費試用版並使用它來測試您的應用程序。

FWIW我現在使用MyDac多年了,我很滿意(表現/獎品/支持)

正如其他人所說,這可能是因為SQLyog沒有加載所有記錄,並且可能將其限制在200左右。

為了解決這個性能問題,您可以使用偷偷摸摸的技巧。 由於您基本上是在啟動時將數據集的緩存加載到應用程序中,因此可以對此進行處理。 加載仍需要6或8秒,但您的應用程序仍然可以啟動並且UI可用。 如果有人在加載之前做了一些需要緩存的東西,你可以簡單地顯示沙漏光標,或者說“請稍等一下......”的消息,直到緩存准備就緒。

在線程中進行數據訪問時要注意的一件事是,您通常需要在線程中創建單獨的數據庫連接。 像這樣的東西:

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按需加載數據,因此第一次訪問它時會很慢,但后續時間會更長,等等。但是,它將取決於您的需求。

HTH

您可以在查詢時使用LIMIT 0,1000,然后在用戶到達遠端時更改它 - 通過檢入OnAfterScroll事件。

在我看來,你應該對你的應用程序和/或數據庫架構三思而后行 - 在處理80K記錄時並不好。 盡量縮小你的查詢 - 如果你不能讓你的生活更簡單 - 沒有人願意

SQLyog可能不會一次加載所有80000行,至少我使用的一些數據庫工具在滾動時會“按需加載”。 如果您絕對需要一次獲取所有記錄,請考慮使用線程執行查詢並填充內部數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM