2012-11-14 30 views
7

Tôi gặp vấn đề với tốc độ truy vấn trong Firebird. Sự chậm chạp trong phân loại và khác biệt.Truy vấn đơn đặt hàng chậm theo/phân biệt

Nếu tôi thử truy vấn trong MySQL thì anh ấy nhanh hơn một giây.

Firebird -> 1,3s một 1,6s MySQL -> 0,3s một 0,4s

Chúng tôi sử dụng cơ sở dữ liệu Firebird trên một máy chủ web/trang web, vì vậy tốc độ là quan trọng.

Thông số kỹ thuật: - Firebird 2.5.1 hoặc 2.5.2 (SuperClassic) 64 bit - 2,13 Ghz (2 bộ vi xử lý) - RAM 4,00 GB

tôi có thể làm gì?

tôi có các bảng sau:

==================================== ================

CREATE TABLE ARTICLE3_1 
(
    IDARTICLE Integer NOT NULL, 
    ITEMSTATUS Integer, 
    ITEMENTRYDATE Integer, 
    ITEMFILTER Integer, 
    ARTIKELNUMMER Varchar(250), 
    ARTIKELNAAM1 Varchar(250), 
    ARTIKELNAAM2 Varchar(250), 
    OMSCHRIJVING_DETAIL Blob sub_type 1, 
    OMSCHRIJVING1 Varchar(250), 
    OMSCHRIJVING2 Varchar(250), 
    ARTIKELNR_LEVERANCIER Varchar(250), 
    MERK Varchar(250), 
    LEVERANCIER Varchar(250), 
    EAN Varchar(250), 
    LINKAANGROEP Varchar(250), 
    LINKAANAANBIEDINGGROEP Varchar(250), 
    LINKAANPOPULAIRGROEP Varchar(250), 
    LINKAANART Varchar(250), 
    ARTGRPNR Varchar(250), 
    SUBGROEP Varchar(250), 
    PRIJSPER Integer, 
    VERKOOPPRIJS Float, 
    ADVIESPRIJS Float, 
    BTWPERC Float, 
    ONLINE Varchar(250), 
    TUSGROEPBIJLINK Varchar(250), 
    AFBEELDINGKLEIN Varchar(250), 
    AFBEELDINGMIDDEL Varchar(250), 
    AFBEELDINGGROOT Varchar(250), 
    ICECATLINK Varchar(250), 
    LINKAANHOMEPAGEGROEP Varchar(250), 
    LINKAANMIJNACCOUNTGROEP Varchar(250), 
    SORTEER Varchar(250), 
    AFBEELDING Varchar(100), 
    FLASH Blob sub_type 1, 
    EENHEID Varchar(250), 
    ALTARTNR1 Varchar(250), 
    ALTARTNR2 Varchar(250), 
    BESTELLENPER Float, 
    INFEED Varchar(250), 
    GOOGLE_TAXONOMIE Varchar(250), 
    FEED_TITEL Varchar(250), 
    FEED_OMSCHRIJVING Blob sub_type 1, 
    PRIMARY KEY (IDARTICLE) 
); 
CREATE INDEX IDX_ARTICLE3_1_2 ON ARTICLE3_1 (MERK); 
CREATE INDEX IDX_ARTICLE3_1_3 ON ARTICLE3_1 (ARTIKELNUMMER); 
CREATE INDEX IDX_ARTICLE3_1_4 ON ARTICLE3_1 (ARTIKELNR_LEVERANCIER); 
CREATE INDEX IDX_ARTICLE3_1_5 ON ARTICLE3_1 (ALTARTNR2); 
CREATE INDEX IDX_ARTICLE3_1_6 ON ARTICLE3_1 (ARTIKELNAAM1); 
CREATE INDEX IDX_ARTICLE3_1_7 ON ARTICLE3_1 (EAN); 

    CREATE TABLE TREE3 
(
    IDLINK Integer NOT NULL, 
    LINKTYPE Integer, 
    IDITEM Integer, 
    ITEMTYPE Integer, 
    IDTARGETLINK Integer, 
    NODEPOSITION Integer, 
    NODELEVEL Integer, 
    IDLAYOUTDATA Integer, 
    IDTEMPLATE Integer, 
    ACTIONDATE Integer, 
    MARKET1 Integer, 
    PRIMARY KEY (IDLINK) 
); 
CREATE INDEX IDX_TREE3_2 ON TREE3 (IDITEM); 
CREATE INDEX IDX_TREE3_3 ON TREE3 (MARKET1); 
CREATE INDEX ITREE13 ON TREE3 (IDTARGETLINK,NODEPOSITION); 
CREATE INDEX ITREE53 ON TREE3 (IDITEM,ITEMTYPE); 

==================================================== 

Các truy vấn trong Firebird:

SELECT FIRST 30 SKIP 0 distinct tr.IdLink, tr.IdTargetLink, tr.IdItem, tr.NodePosition 
FROM Tree3 tr 
inner join article3_1 art on art.idarticle = Tr.iditem 
WHERE tr.ItemType = 2 AND tr.Market1 = 1 
AND ((art.IDARTICLE > 0) AND ( (LOWER(art.Artikelnummer) like '%a4 papier%') OR ((LOWER(art.Artikelnummer) like 'a4') 
AND (LOWER(art.Artikelnummer) like 'papier')) OR (LOWER(art.Artikelnaam1) like '%a4 papier%') OR ((LOWER(art.Artikelnaam1) like '%a4%') 
AND (LOWER(art.Artikelnaam1) like '%papier%')) OR (LOWER(art.Artikelnaam2) like '%a4 papier%') OR ((LOWER(art.Artikelnaam2) like '%a4%') 
AND (LOWER(art.Artikelnaam2) like '%papier%')) OR (LOWER(art.Artikelnr_leverancier) like '%a4 papier%') OR ((LOWER(art.Artikelnr_leverancier) like '%a4%') 
AND (LOWER(art.Artikelnr_leverancier) like '%papier%')) OR (LOWER(art.Merk) like '%a4 papier%') OR ((LOWER(art.Merk) like '%a4%') 
AND (LOWER(art.Merk) like '%papier%')) OR (LOWER(art.EAN) like '%a4 papier%') OR ((LOWER(art.EAN) like '%a4%') 
AND (LOWER(art.EAN) like '%papier%')) OR (LOWER(art.AltArtnr1) like '%a4 papier%') OR ((LOWER(art.AltArtnr1) like '%a4%') 
AND (LOWER(art.AltArtnr1) like '%papier%')) OR (LOWER(art.AltArtnr2) like '%a4 papier%') OR ((LOWER(art.AltArtnr2) like '%a4%') 
AND (LOWER(art.AltArtnr2) like '%papier%')))) 
AND tr.NODELEVEL =5 and tr.LINKTYPE <> 5 
ORDER BY tr.NodePosition 

Các truy vấn trong MySQL:

SELECT distinct tr.IdLink, tr.IdTargetLink, tr.IdItem, tr.NodePosition 
FROM Tree3 tr 
inner join article3_1 art on art.idarticle = Tr.iditem 
WHERE tr.ItemType = 2 AND tr.Market1 = 1 
AND ((art.IDARTICLE > 0) AND ( (LCASE(art.Artikelnummer) like '%a4 papier%') OR ((LCASE(art.Artikelnummer) like 'a4') 
AND (LCASE(art.Artikelnummer) like 'papier')) OR (LCASE(art.Artikelnaam1) like '%a4 papier%') OR ((LCASE(art.Artikelnaam1) like '%a4%') 
AND (LCASE(art.Artikelnaam1) like '%papier%')) OR (LCASE(art.Artikelnaam2) like '%a4 papier%') OR ((LCASE(art.Artikelnaam2) like '%a4%') 
AND (LCASE(art.Artikelnaam2) like '%papier%')) OR (LCASE(art.Artikelnr_leverancier) like '%a4 papier%') OR ((LCASE(art.Artikelnr_leverancier) like '%a4%') 
AND (LCASE(art.Artikelnr_leverancier) like '%papier%')) OR (LCASE(art.Merk) like '%a4 papier%') OR ((LCASE(art.Merk) like '%a4%') 
AND (LCASE(art.Merk) like '%papier%')) OR (LCASE(art.EAN) like '%a4 papier%') OR ((LCASE(art.EAN) like '%a4%') 
AND (LCASE(art.EAN) like '%papier%')) OR (LCASE(art.AltArtnr1) like '%a4 papier%') OR ((LCASE(art.AltArtnr1) like '%a4%') 
AND (LCASE(art.AltArtnr1) like '%papier%')) OR (LCASE(art.AltArtnr2) like '%a4 papier%') OR ((LCASE(art.AltArtnr2) like '%a4%') 
AND (LCASE(art.AltArtnr2) like '%papier%')))) 
AND tr.NODELEVEL =5 and tr.LINKTYPE <> 5 
ORDER BY tr.NodePosition LIMIT 30; 

================================================= ===

tôi có truy vấn thực hiện với FlameRobin:

> Prepare time: 0.016s Field #01: TREE3.IDLINK Alias:IDLINK Type:INTEGER 
> Field #02: TREE3.IDTARGETLINK Alias:IDTARGETLINK Type:INTEGER Field 
> #03: TREE3.IDITEM Alias:IDITEM Type:INTEGER Field #04: TREE3.NODEPOSITION Alias:NODEPOSITION Type:INTEGER PLAN SORT (SORT 
> (JOIN (TR INDEX (IDX_TREE3_2, IDX_TREE3_3), ART INDEX 
> (RDB$PRIMARY2)))) 
> 
> 873424 fetches, 0 marks, 12892 reads, 0 writes. 0 inserts, 0 updates, 
> 0 deletes, 380580 index, 0 seq. Delta memory: 1784 bytes. Total 
> execution time: 1.311s 

Cảm ơn bạn!

+0

Tree3 là gì? Bạn đã liệt kê bảng article3_1 hai lần. – nater

+0

Rất tiếc, tôi đã thêm hai lần cùng một siêu dữ liệu. – VanderLinde

Trả lời

0

Điều này có thể hơi cũ nhưng bây giờ hy vọng vẫn có thể hữu ích.

Nói chung, khác biệt và thứ tự theo các thao tác yêu cầu sắp xếp. Sắp xếp được hỗ trợ bởi các chỉ mục. Xem xét việc tạo các chỉ mục cho các cột được chỉ định theo thứ tự theo mệnh đề - NodePosition, chỉ mục khác duy nhất trên nó mà tôi có thể thấy là kết hợp với một cột khác để chỉ mục không được tham vấn theo thứ tự. Đối với sự khác biệt, bạn có thể thử tạo chỉ mục tổng hợp cho các cột tr.IdLink, tr.IdTargetLink, tr.IdItem, tr.NodePosition hoặc từng cột riêng lẻ. (Tôi không quá chắc chắn về sự khác biệt sẽ được giúp đỡ bởi các chỉ mục nhưng đáng để thử).

Những thứ khác cần xem xét: mệnh đề where của bạn sử dụng hàm - hàm khi được sử dụng trong ngữ cảnh này sẽ cho kết quả quét toàn bộ bảng và thậm chí không thể xem chỉ mục của bạn. Tôi không tin mySql hỗ trợ các chỉ mục dựa trên chức năng, không chắc chắn về FireBird. Nhưng nó có thể được làm việc xung quanh bằng cách tạo ra một cột khác có thể giữ kết quả của LOWER (cột), bạn sẽ cần phải duy trì cột đó bằng cách sử dụng các trigger nếu có.

HOẶC điều kiện và LIKE '% a4%' cũng sẽ dẫn đến quét toàn bộ bảng. Tôi nhận thấy rằng logic nghiệp vụ của bạn có thể không cho phép bạn bỏ char ký tự đại diện từ đầu chuỗi '% a4%' để có thể cải thiện các trường hợp sử dụng đó, bạn có thể xem xét truy vấn phụ - trước tiên hãy thử thu hẹp kết quả của bạn càng nhiều càng tốt có thể trong truy vấn phụ tránh bất kỳ LIKE hoặc OR nào và sau đó bọc kết quả đó bằng một truy vấn cha mẹ sẽ tiếp tục lọc kết quả (đặt truy vấn phụ vào mệnh đề FROM). Vì vậy, trong truy vấn phụ của bạn, bạn sẽ có các điều kiện sau: tr.ItemType = 2 AND tr.Market1 = 1 và tr.NODELEVEL = 5 và tr.LinkType <> 5

+0

Có, Firebird 2+ cho phép lập chỉ mục trên các biểu thức/hàm: http://www.firebirdsql.org/refdocs/langrefupd20-create-index.html#langrefupd20-creatind-on-expr – reiniero

1

Yip tránh DISTINCT và như thế nào nếu bạn có thể, Tối ưu hóa DISTINCT http://dev.mysql.com/doc/refman/5.0/en/distinct-optimization.html

Hãy thử một truy vấn lồng nhau với nhóm bởi thay vì riêng biệt. Tôi sử dụng thông tin này để giải quyết vấn đề khi sử dụng nhóm theo số & theo thứ tự.

select * from ({the rest of the query}) as some_table group by {my distinct column};

Ngoài ra tôi không thể nhìn thấy động cơ bảng của bạn, nhưng MyISAM là tốt hơn để tìm kiếm văn bản đầy đủ (chứ không phải là InnoDB). Ngoài ra nó có thể là giá trị nhìn vào Solr để tìm kiếm toàn văn. Một chút về đường cong học tập để thiết lập, nhưng bạn có thể lập chỉ mục các bảng mysql rồi thực hiện tìm kiếm đối sánh từng phần trên nhiều cột. Với những thứ như thúc đẩy và khiếp sợ.

Xem truy vấn bên dưới có bất kỳ lợi ích hiệu suất nào không.

select * from (SELECT tr.IdLink, tr.IdTargetLink, tr.IdItem, tr.NodePosition 
FROM Tree3 tr 
inner join article3_1 art on art.idarticle = Tr.iditem 
WHERE tr.ItemType = 2 AND tr.Market1 = 1 
AND ((art.IDARTICLE > 0) AND ( (LCASE(art.Artikelnummer) like '%a4 papier%') OR (
(LCASE(art.Artikelnummer) like 'a4') 
AND (LCASE(art.Artikelnummer) like 'papier')) OR (LCASE(art.Artikelnaam1) like '%a4 papier%') OR ((LCASE(art.Artikelnaam1) like '%a4%') 
AND (LCASE(art.Artikelnaam1) like '%papier%')) OR (LCASE(art.Artikelnaam2) like '%a4 papier%') OR ((LCASE(art.Artikelnaam2) like '%a4%') 
AND (LCASE(art.Artikelnaam2) like '%papier%')) OR (LCASE(art.Artikelnr_leverancier) 
like '%a4 papier%') OR ((LCASE(art.Artikelnr_leverancier) like '%a4%') 
AND (LCASE(art.Artikelnr_leverancier) like '%papier%')) OR (LCASE(art.Merk) like '%a4 papier%') OR ((LCASE(art.Merk) like '%a4%') 
AND (LCASE(art.Merk) like '%papier%')) OR (LCASE(art.EAN) like '%a4 papier%') OR (
(LCASE(art.EAN) like '%a4%') 
AND (LCASE(art.EAN) like '%papier%')) OR (LCASE(art.AltArtnr1) like '%a4 papier%') OR  
((LCASE(art.AltArtnr1) like '%a4%') 
AND (LCASE(art.AltArtnr1) like '%papier%')) OR (LCASE(art.AltArtnr2) like '%a4 papier%') OR ((LCASE(art.AltArtnr2) like '%a4%') 
AND (LCASE(art.AltArtnr2) like '%papier%')))) 
AND tr.NODELEVEL =5 and tr.LINKTYPE <> 5 
ORDER BY tr.NodePosition LIMIT 30) 
as some_table group by IdLink; 
Các vấn đề liên quan