2015-06-18 56 views
0

我有一個關於要執行的查詢的問題,但我不知道什麼是最好的性能。我需要將所有單詞排除在與表單詞過濾器關聯的單詞之外。查詢性能 - '左連接爲空'vs'不存在選擇'

查詢的輸出是正確的,但也許有更好的解決方案。我幾乎沒有關於查詢計劃的知識,現在我正試圖理解它。

SELECT CONCAT(SPACE(1), UCASE(stocknews.word.word), SPACE(1)) AS word, stocknews.word.language 
FROM stocknews.word 
WHERE NOT EXISTS (SELECT word_id FROM stocknews.wordfilter WHERE stocknews.word.id = word_id) 
AND user_id = 1 

+----+--------------+------------+-------+---------------+---------+---------+-------+------+-------------+ 
| id | select_type | table  | type | possible_keys | key  | key_len | ref | rows | extra  | 
+----+--------------+------------+-------+---------------+---------+---------+-------+------+-------------+ 
| 1 | PRIMARY  | word  | ref | user_id  | user_id | 4  | const | 843 | Using where | 
| 2 | MATERIALIZED | wordfilter | index | PRIMARY  | PRIMARY | 756  |  | 16 | Using index | 
+----+--------------+------------+-------+---------------+---------+---------+-------+------+-------------+ 

反對

SELECT CONCAT(SPACE(1), UCASE(stocknews.word.word), SPACE(1)) AS word, stocknews.word.language 
FROM stocknews.word 
LEFT JOIN stocknews.wordfilter ON stocknews.word.id = stocknews.wordfilter.word_id 
WHERE stocknews.wordfilter.word_id IS NULL AND user_id = 1 

+----+-------------+------------+------+---------------+---------+---------+---------+------+--------------------------------------+ 
| id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows | extra        | 
+----+-------------+------------+------+---------------+---------+---------+---------+------+--------------------------------------+ 
| 1 | SIMPLE  | word  | ref | user_id  | user_id | 4  | const | 843 |          | 
| 1 | SIMPLE  | wordfilter | ref | PRIMARY  | PRIMARY | 4  | word.id | 1 | Using where; Using index; Not exists | 
+----+-------------+------------+------+---------------+---------+---------+---------+------+--------------------------------------+ 

歡迎任何幫助!解釋會很好。

編輯:

對於查詢1:

+----------------------------+-------+ 
| Variable_name    | Value | 
+----------------------------+-------+ 
| Handler_commit    | 1  | 
| Handler_delete    | 0  | 
| Handler_discover   | 0  | 
| Handler_external_lock  | 0  | 
| Handler_icp_attempts  | 0  | 
| Handler_icp_match   | 0  | 
| Handler_mrr_init   | 0  | 
| Handler_mrr_key_refills | 0  | 
| Handler_mrr_rowid_refills | 0  | 
| Handler_prepare   | 0  | 
| Handler_read_first   | 1  | 
| Handler_read_key   | 1044 | 
| Handler_read_last   | 0  | 
| Handler_read_next   | 859 | 
| Handler_read_prev   | 0  | 
| Handler_read_rnd   | 0  | 
| Handler_read_rnd_deleted | 0  | 
| Handler_read_rnd_next  | 0  | 
| Handler_rollback   | 0  | 
| Handler_savepoint   | 0  | 
| Handler_savepoint_rollback | 0  | 
| Handler_tmp_update   | 0  | 
| Handler_tmp_write   | 215 | 
| Handler_update    | 0  | 
| Handler_write    | 0  | 
+----------------------------+-------+ 
25 rows in set (0.00 sec) 

對於查詢2:

+----------------------------+-------+ 
| Variable_name    | Value | 
+----------------------------+-------+ 
| Handler_commit    | 1  | 
| Handler_delete    | 0  | 
| Handler_discover   | 0  | 
| Handler_external_lock  | 0  | 
| Handler_icp_attempts  | 0  | 
| Handler_icp_match   | 0  | 
| Handler_mrr_init   | 0  | 
| Handler_mrr_key_refills | 0  | 
| Handler_mrr_rowid_refills | 0  | 
| Handler_prepare   | 0  | 
| Handler_read_first   | 0  | 
| Handler_read_key   | 844 | 
| Handler_read_last   | 0  | 
| Handler_read_next   | 843 | 
| Handler_read_prev   | 0  | 
| Handler_read_rnd   | 0  | 
| Handler_read_rnd_deleted | 0  | 
| Handler_read_rnd_next  | 0  | 
| Handler_rollback   | 0  | 
| Handler_savepoint   | 0  | 
| Handler_savepoint_rollback | 0  | 
| Handler_tmp_update   | 0  | 
| Handler_tmp_write   | 0  | 
| Handler_update    | 0  | 
| Handler_write    | 0  | 
+----------------------------+-------+ 
+0

您是否嘗試過並且比較了性能?一般來說(至少在SQL Server中,不確定MariaDB),如果你的表正確索引,'EXISTS'和'NOT EXISTS'執行得更快,因爲它們是短路操作。一旦找到記錄,就會根據您的查詢將其排除或包含在內。 'LEFT JOIN'包括所有的記錄,並且以'IS NULL'標準結尾進行過濾。 –

+0

我在一個小數據集上嘗試了這兩種方法,兩者都有相同的結果。感謝您提供的信息,我幾乎可以確定我的索引是否正確設置。我想我需要製作一個更大的數據集來看看有什麼不同。我的主要問題是聽到查詢使其更快或更慢。所以我猜'NOT EXISTS'方法更快。我將用更大的數據集對其進行測試,並報告實際查詢的速度。謝謝 –

+0

當_word_中有13.000條記錄和_wordfilter_中有5000條記錄時,'NOT EXISTS'方法似乎更快了@ –

回答

0

這似乎是兩種製劑之間緊密的賽程。 (其他示例可能會顯示更清晰的贏家。)

從HANDLER值中查詢1執行了更多的read_keys和一些寫操作(與MATERIALIZED配合使用)。其他數字大致相同。因此,我得出結論:查詢1速度較慢 - 儘管可能不足以產生很大的差異。

我投給LEFT JOIN作爲更好的查詢模式(在這種情況下)