簡體   English   中英

我該如何優化這個MySQL查詢?

[英]How can I optimise this MySQL query?

我在包含超過300,000,000(是,三億)行的數據庫的PHP腳本中使用以下MySQL查詢。 我知道這是非常耗費資源的,運行這一個查詢需要很長時間。 有誰知道如何優化查詢或以更快的方式獲取信息?

我需要能夠使用1到15之間的任何整數代替MID()中的14。 我還需要能夠在LIKE子句中匹配相同范圍內的長度字符串。

表信息:

games | longint, unsigned, Primary Key
win   | bit(1)
loss  | bit(1)

示例查詢:

SELECT MID(`game`,14,1) AS `move`,
       COUNT(*) AS `games`,
       SUM(`win`) AS `wins`,
       SUM(`loss`) AS `losses`
FROM `games`
WHERE `game` LIKE '1112223334%'
GROUP BY MID(`game`,1,14)

在此先感謝您的幫助!

首先,在游戲領域有一個索引...... :)

查詢看起來簡單明了,但它隱藏了可能需要更改數據庫設計的事實。

在這種情況下,我總是喜歡維護一個包含聚合數據的字段,每天,每個用戶或任何其他軸。 這樣,您可以擁有聚合相關數據並將其保存在數據庫中的日常任務。

如果您經常調用此查詢,則應使用降低插入效率的原則來提高檢索效率。

看起來game列存儲了此查詢正在使用的兩個(或可能更多)不同的內容:

  1. game開始時過濾(前10個字符)
  2. 分組並返回MID(游戲,1,14) (我假設其中一個MID表達式是拼寫錯誤。

我將其拆分,以便您不必在game列上使用字符串操作,並在新列上放置索引,以便您可以正確地過濾和分組它們。

這個查詢正在進行大量的轉換(長到字符串)和字符串操作,如果表是規范化的(如每列中的一條信息而不是像現在這樣的多條信息)。

game列保留game_filter ,並根據它創建一個game_filter字符串列,以便在WHERE子句中使用。 然后設置一個game_group列,並在插入時使用MID表達式填充它。 將這兩列設置為聚簇索引,首先是game_filter ,然后是game_group

查詢很簡單,除了確保有所有必要的索引(顯然是“游戲”字段)之外,通過僅重寫查詢可能沒有明顯的方法使其更快。 可能需要對數據結構進行一些修改。

一種方法:預先計算總和。 這些記錄中的每一個都很可能具有create_date或自動增量的鍵字段。 預先計算所有記錄的總和,此字段≤X,將結果放入邊表,然后您只需計算所有記錄> X,然后用預先計算的結果匯總這些部分結果。

您可以預先計算MID( game ,14,14)和MID( game ,1,14),並將game的前十位數存儲在一個單獨的game列表列中,該列被編入索引。

調查是否可以只存儲預先計算的值的聚合表,以便在插入時增加計數和贏或輸列列也可能是一個想法。

SELECT  MID(`game`,14,1) AS `move`,
        COUNT(*) AS `games`,
        SUM(`win`) AS `wins`,
        SUM(`loss`) AS `losses`
FROM    `games`
WHERE   `game` LIKE '1112223334%'

game上創建索引:

CREATE INDEX ix_games_game ON games (game)

並重寫您的查詢,如下所示:

SELECT  move,
        (
        SELECT  COUNT(*)
        FROM    games
        WHERE   game >= move
                AND game < CONCAT(SUBSTRING(move, 1, 13), CHR(ASCII(SUBSTRING(move, 14, 1)) + 1))
        ),
        (
        SELECT  SUM(win)
        FROM    games
        WHERE   game >= move
                AND game < CONCAT(SUBSTRING(move, 1, 13), CHR(ASCII(SUBSTRING(move, 14, 1)) + 1))
        ),
        (
        SELECT  SUM(lose)
        FROM    games
        WHERE   game >= move
                AND game < CONCAT(SUBSTRING(move, 1, 13), CHR(ASCII(SUBSTRING(move, 14, 1)) + 1))
        )
FROM    (
        SELECT  DISTINCT SUBSTRING(q.game, 1, 14) AS move
        FROM    games
        WHERE   game LIKE '1112223334%'
        ) q

這將有助於更有效地使用game索引。

你可以用Memcache或類似的東西緩存結果集嗎? 這將有助於重復點擊。 即使您只將結果集緩存幾秒鍾,也可以避免大量的數據庫讀取。

暫無
暫無

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

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