2017-08-28 95 views
0

在MySQL 5.6.34(我的新開發服務器)和MariaDB 10.2.8(我的新生產服務器,我認爲我今天終於部署代碼的地方 - 完全相同的數據庫結構和數據 - 嘆氣!),MySQL正在工作,而MariaDB不在。這是在MySQL 5.0.95上工作良好的代碼。我將查詢簡化爲顯示問題的最小示例 - 似乎GROUP_CONCAT()和子查詢不混合。下面是該查詢:MariaDB:group_concat子查詢失敗

SELECT person.PersonID, 
GROUP_CONCAT(CategoryID ORDER BY CategoryID SEPARATOR ',') AS categories 
FROM person LEFT JOIN percat ON person.PersonID=percat.PersonID 
WHERE person.PersonID IN (SELECT PersonID FROM action WHERE ActionTypeID=3) 
GROUP BY person.PersonID 

,這裏是屏幕截圖,顯示所有三個表所涉及的結構的複合圖像:

enter image description here

在MySQL,它工作得很好,因爲它一直多年。下面是結果和EXPLAIN

MySQL 5.6.34

這是瘋狂的結果我得到MariaDB的:

enter image description here

我不知道數據庫引擎不夠好內部工作按照EXPLAIN,但我認爲線索是在那裏。我發現這聽起來有點相關,但我不太明白他們在說什麼,更重要的是,我應該怎麼處理這件事。

回答

1

這是一個錯誤,顯然它與您發現的錯誤並不完全相同(因爲上述錯誤報告中的測試用例在10.2.8上正常工作,而您的確沒有)。請隨時在MariaDB JIRA舉報新的報告。

同時,我認爲你應該能夠在您的CNF文件中設置

optimizer_switch=orderby_uses_equalities=off 

解決它。這是一個新啓用的優化,顯然不完美。


UPDATE:該錯誤是現在報告爲https://jira.mariadb.org/browse/MDEV-13694

+0

我似乎無法打開如果關閉 - 顯然我做錯了。在'/ etc/my.cnf',section ['mysqld]'中,我添加了'optimizer_switch = orderby_uses_equalities = off'(我嘗試了使用和不使用單引號 - 我在網絡上看到了這兩個示例)並重新啓動了mysqld也有奇怪的行爲 - 它不會給我的ssh提示符,直到我等待一段時間後按^ C)。但是'SELECT @@ optimizer_switch \ G'表示'orderby_uses_equalities'仍然打開,並且查詢行爲沒有變化。 – OsakaWebbie

+1

該部分和線條都很好。首先,檢查你的服務器實際上是否重啓(例如,通過驗證'SHOW STATUS LIKE'Uptime''和/或錯誤日誌)。聽起來服務器並沒有真正關閉,然後嘗試重新啓動,並開始爭奪數據庫,例如用於鎖定詠歎調控制文件等。如果服務器確實重新啓動,另一個可能的原因是您的安裝不使用此cnf文件。你可以在optimizer_switch之後放置一些獨特的東西,例如'lock_wait_timeout = 42'(或者你會認識的任何東西),看看它是否被拾取。 – elenst

+0

是的,就是這樣 - 它沒有真正重新啓動(我錯誤地執行了命令)。你的解決方法就像一個魅力!當我有更多的時間時,我會致力於簡化我的代碼,但現在,我可以繼續推動我的新服務器,謝謝你。 – OsakaWebbie

0

解決方法這不會回答爲什麼是有區別的,但你應該添加DISTINCTGROUP_CONCAT

「爲什麼」可能的答案是根植於Optimizers。自5.0版本以來發生了很多變化。 5.6有很多新的代碼;與此同時,MariaDB正在分成10.0。在這個分叉中,優化者顯着地分歧。 10.2已經向前移動了,但未必在優化這種類型的查詢

改進的查詢可以對查詢做幾件事情。有些可能會使其更快:

SELECT p.PersonID, 
     (SELECT GROUP_CONCAT(pc.CategoryID 
           ORDER BY CategoryID SEPARATOR ',') 
      FROM percat 
      WHERE PersonID = p.PersonID 
     ) AS categories 
    FROM person 
    JOIN action AS a ON p.PersonID = a.PersonID 
    WHERE ActionTypeID = 3 
    GROUP BY p.PersonID 

改造LEFT JOIN可能會減少對GROUP BY負載。可能GROUP BY可以被刪除。由於PRIMARY KEY(PersonID, CategoryID),應該不需要DISTINCT

需要索引這個「覆蓋索引」會加快速度:INDEX(ActionTypeID, PersonID)

+0

添加DISTINCT只消除了重複的CategoryID - 它對主要問題沒有影響:當應該有倍數時,我仍然只獲得一個人記錄。關於通過將子查詢更改爲連接進行優化的想法,請注意我在此處共享的查詢是超級簡化的 - 在我的真實應用程序中,用戶可以組合各種搜索條件,並且必須以編程方式將其選擇一個工作查詢。如果沒有子查詢,我一直無法想出辦法。 – OsakaWebbie

+0

'GROUP BY PersonID' _causes_每個人只有一行。我想我不知道你想要什麼。而你的樣本輸出每人只有一行。模擬你想要的輸出。 –

+0

有四個人匹配WHERE,所以應該返回四行。正確的輸出可以在「On MySQL ...」屏幕截圖中看到。我不知道爲什麼前三個人不回來,但這是主要問題。 – OsakaWebbie