2014-10-30 25 views
0

我有一個已經在使用的數據庫,我必須提高使用此數據庫的系統的性能。如何在不更改數據庫結構的情況下提高Mysql數據庫性能

循環中有兩個主要查詢運行約1000次,並且此查詢每個都有3個其他表的內部連接。這反過來使系統非常慢。
我試着從循環中刪除查詢,並只提取一次所有數據並在PHP中處理它。但是這會給內存(RAM)帶來很多負擔,並且如果有2個或更多的客戶端嘗試使用該系統,系統就會掛起。

即使在刪除過期的數據後,表中仍有大量數據。
我附上了下面的查詢。
任何人都可以幫助我解決這個問題嗎?

select * from inventory 
where (region_id = 38 or region_id = -1) 
    and (tour_opp_id = 410 or tour_opp_id = -1) 
    and room_plan_id = 141 and meal_plan_id = 1 and bed_type_id = 1 and hotel_id = 1059 
    and FIND_IN_SET(supplier_code, 'QOA,QTE,QM,TEST,TEST1,MQE1,MQE3,PERR,QKT') 
    and (('2014-11-14' between from_date and to_date)) 
order by hotel_id desc ,supplier_code desc, region_id desc,tour_opp_id desc,inventory.inventory_id desc 


SELECT * ,pinfo.fri as pi_day_fri,pinfoadd.fri as pa_day_fri,pinfochld.fri as pc_day_fri 
FROM `profit_markup` 
    inner join profit_markup_info as pinfo on pinfo.profit_id = profit_markup.profit_markup_id 
    inner join profit_markup_add_info as pinfoadd on pinfoadd.profit_id = profit_markup.profit_markup_id 
    inner join profit_markup_child_info as pinfochld on pinfochld.profit_id = profit_markup.profit_markup_id 
where profit_markup.hotel_id = 1059 and (`booking_channel` = 1 or `booking_channel` = 2) 
    and (`rate_region` = -1 or `rate_region` = 128) 
    and ((period_from <= '2014-11-14' and period_to >= '2014-11-14')) 
ORDER BY profit_markup.hotel_id DESC,supplier_code desc, rate_region desc,operators_list desc, profit_markup_id DESC 
+0

你能告訴你顯示創建表嗎?另外,你可以向隊列展示你的解釋嗎?服務器規格又是什麼? – Jaylen 2014-10-30 06:05:02

+0

你爲什麼使用*而不是列出字段?另外,你可以展示你如何循環記錄。這些表如何更新(每小時/每秒/小時?)您使用「OR」而不是「IN」的任何原因? – Jaylen 2014-10-30 06:44:17

回答

0

因爲我們還沒有看到你的SHOW CREATE TABLES;EXPLAIN EXTENDED計劃很難給你1個回答

但考慮到您的查詢一般來說「BTW我重新寫了下面的」

SELECT 
    hotel_id, supplier_code, region_id, tour_opp_id, inventory_id 
FROM 
    inventory 
WHERE 
    region_id IN (38, -1) 
    AND tour_opp_id IN (410, -1) 
    AND room_plan_id IN (141, 1) 
    AND bed_type_id IN (1, 1059) 
    AND supplier_code IN ('QOA', 'QTE', 'QM', 'TEST', 'TEST1', 'MQE1', 'MQE3', 'PERR', 'QKT') 
    AND ('2014-11-14' BETWEEN from_date AND to_date) 
ORDER BY 
    hotel_id DESC, supplier_code DESC, region_id DESC, tour_opp_id DESC, inventory_id DESC 
  1. 請勿使用*來獲取所有列。你應該列出你真正需要的列。使用*只是編寫查詢的一種懶惰方式。限制列將限制正在選擇的數據大小。

  2. 更新/插入/刪除庫存記錄的頻率如何?如果不是太頻繁,那麼你可以考慮使用SQL_CACHE。但是,如果使用它,緩存查詢會導致問題,並且庫存表經常更新。另外,要使用查詢緩存,您必須檢查服務器上的值query_cache_typeSHOW GLOBAL VARIABLES LIKE 'query_cache_type';。如果將其設置爲「0」,則緩存功能將被禁用,並且SQL_CACHE將被忽略。如果它設置爲1,那麼服務器將緩存所有查詢,除非您使用NO_SQL_CACHE不要告訴它。如果該選項設置爲2,則MySQL將僅在使用SQL_CACHE子句的情況下緩存查詢。 here is documentation about query_cache_type

  3. 如果您有順序的下面列的索引它會幫助你(hotel_id, supplier_code, region_id, tour_opp_id, inventory_id)

    ALTER TABLE inventory 
    ADD INDEX (hotel_id, supplier_code, region_id, tour_opp_id, inventory_id); 
    
  4. 如果您的服務器作爲最有可能你在這裏發出有關可能增加sort_buffer_size是你正在做的太很多排序。

至於第二個查詢「BTW我重新寫了下面的」

SELECT 
    *, pinfo.fri as pi_day_fri, 
    pinfoadd.fri as pa_day_fri, 
    pinfochld.fri as pc_day_fri 
FROM 
    profit_markup 
INNER JOIN 
    profit_markup_info AS pinfo ON pinfo.profit_id = profit_markup.profit_markup_id 
INNER JOIN 
    profit_markup_add_info AS pinfoadd ON pinfoadd.profit_id = profit_markup.profit_markup_id 
INNER JOIN 
    profit_markup_child_info AS pinfochld ON pinfochld.profit_id = profit_markup.profit_markup_id 
WHERE 
    profit_markup.hotel_id = 1059 
    AND booking_channel IN (1, 2) 
    AND rate_region IN (-1, 128) 
    AND period_from <= '2014-11-14' 
    AND period_to >= '2014-11-14' 
ORDER BY 
    profit_markup.hotel_id DESC, supplier_code DESC, rate_region DESC, 
    operators_list DESC, profit_markup_id DESC 
  1. 再次從查詢中杜絕使用*

  2. 確保下面的列具有相同的類型/排序規則和相同的大小。 pinfo.profit_id, profit_markup.profit_markup_id, pinfoadd.profit_id, pinfochld.profit_id並且每個人都必須在每張桌子上都有一個索引。如果列有不同的類型,那麼MySQL每次都必須轉換數據才能加入記錄。即使你有索引,它也會變慢。此外,如果這些列是字符類型(即VARCHAR()),請確保它們的編號爲CHAR(),排序規則爲latin1_general_ci,因爲查找ID的速度會更快,但是如果您使用INT()更好。

  3. 使用第3和第4招我列出了上述查詢

  4. 嘗試使用STRAIGHT_JOIN「你必須知道你在這裏做什麼或它會咬你!」這是一個很好的線索關於這When to use STRAIGHT_JOIN with MySQL

我希望這可以幫助。

0

對於第一個查詢,我不知道如果你能做到多少(假設你已經編制了索引通過排序字段)除了*與列名替換(不要指望這增加演出劇烈)。

對於第二個查詢,在通過循環並放入選擇參數之前,可以創建一個視圖,將所有表連接起來並進行排序,然後使用預準備語句從視圖中選擇並在循環中綁定參數。另外,如果您的php服務器和數據庫服務器位於兩個不同的地方,那麼最好是通過數據庫中的存儲過程進行選擇。

(如果沒有作品出來,然後內存緩存是要走的路......雖然我個人從來沒有這樣做)

0

這裏有提高查詢性能不是數據庫的性能。

對於這兩個查詢首先檢查索引是否在WHERE和ON(Join)子句列上可用,如果缺少索引,則必須添加索引以提高查詢性能。

在創建索引之前檢查解釋平面。

如果可能的話,讓我看看這兩個查詢的解釋平面,這將有助於我們。

相關問題