2013-07-16 225 views
0

我得到了這個查詢工作,但它真的很慢。MySQL查詢緩慢運行

我想用以下查詢:1隨機(id,word,meaning)和1隨機不正確任何其他詞的含義。如何通過我的查詢獲得更好的性能?

$offset_result = mysql_query("SELECT FLOOR(RAND() * COUNT(*)) AS offset FROM words WHERE APPROVAL=1 AND PERIOD<".$_SESSION['statistics']['d']." OR (PERIOD=".$_SESSION['statistics']['d']." AND WEEK<=".$_SESSION['statistics']['h'].")"); 
    $offset_row = mysql_fetch_object($offset_result); 
    $offset = $offset_row->offset; 
    $words = mysql_query("SELECT ID,WORD,MEANING, 
    (SELECT MEANING FROM words WHERE ID!=w.ID AND APPROVAL=1 AND WORD!=w.WORD AND NOT FIND_IN_SET(w.MEANING, OTHER_MEANING) AND ID >= (SELECT FLOOR(MAX(ID) * RAND()) FROM words) ORDER BY ID LIMIT 1) AS INCORRECT 
    FROM words w 
    LIMIT $offset, 1"); 

這裏是表格佈局

CREATE TABLE words (
    ID int(11) NOT NULL AUTO_INCREMENT, 
    APPROVAL tinyint(1) NOT NULL DEFAULT '1', 
    WORD varchar(255) COLLATE utf8_turkish_ci NOT NULL, 
    MEANING varchar(255) COLLATE utf8_turkish_ci NOT NULL, 
    OTHER_MEANING varchar(255) COLLATE utf8_turkish_ci NOT NULL, 
    PERIOD tinyint(1) NOT NULL, 
    WEEK tinyint(2) NOT NULL, 
    PRIMARY KEY (ID), 
    KEY APPROVAL (APPROVAL)) 
    ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_turkish_ci AUTO_INCREMENT=769 ; 
+0

我不確定我完全理解了這個問題,但您可以使用SELECT ... ORDER BY RAND()LIMIT 1'從結果中獲取一個隨機行。 –

+1

那你的數據庫模式是什麼,你設置了哪些索引? –

+0

**您需要向我們展示表和索引定義。**診斷慢查詢需要全表和索引定義,而不僅僅是描述或釋義。也許你的表格定義不好。也許索引沒有正確創建。也許你沒有一個你認爲你做過的那個專欄的索引。沒有看到表和索引定義,我們不能說。如果你知道如何做一個'EXPLAIN'或者得到一個執行計劃,那就把結果也放在問題中。 –

回答

0

最大的問題是!=not in條款。如果你重寫這個不使用這些函數,你會變得更好。

guide

摘要

MySQL能夠優化所有三種方法進行排序的嵌套循環ANTI 的JOIN。

它將從t_left中獲取每個值並在 t_right.value的索引中查找它。在索引命中或索引未命中的情況下, 對應的謂詞將立即分別返回FALSE或TRUE, ,並且立即返回t_left或不返回 的行的決定,而不檢查t_right中的其他行。

但是,這三種方法產生三種不同的計劃,它們是由三個不同的代碼段執行的 。執行 EXISTS謂詞的代碼比執行 index_subquery和LEFT JOIN的代碼效率低30%左右,並優化爲使用Not exists方法。

這就是爲什麼在MySQL中搜索缺失值的最佳方法是使用 a LEFT JOIN/IS NULL或NOT IN,而不是NOT EXISTS。

+0

'FIND_IN_SET(w.MEANING,OTHER_MEANING)!= 1'和'NOT FIND_IN_SET(w.MEANING,OTHER_MEANING)'我認爲沒有任何不同的表現。 – gokhan