何ヶ月にもわたる冗長なデータを保持することで、私は自分のデータベースを整理しようとしています。残念ながら、不要な行を削除すると思われるクエリを実行すると、(サーバー自体ではなく) mySQL サーバー インスタンスがクラッシュしているようです。
DELETE w FROM word w WHERE NOT EXISTS(
SELECT NULL FROM translation t WHERE t.WordID = w.KeyID LIMIT 1
) AND NOT EXISTS (
SELECT NULL FROM namespace n WHERE n.IdentifierID = w.KeyID LIMIT 1
)
このクエリをより効率的にする方法はありますか?
edit #1 SQL Workbench からのエラー: エラー コード: 1053。サーバーのシャットダウンが進行中です
編集 #2次のクエリも失敗します。おそらく、テーブルを一緒に接着することに何か問題があることを示していますか?
SELECT w.* FROM word w
LEFT JOIN translation t ON t.WordID = w.KeyID
LEFT JOIN namespace n ON n.IdentifierID = w.KeyID
WHERE t.TranslationID IS NULL AND n.NamespaceID IS NULL
ただし、サブクエリでハードコードされた値を使用しても機能します。
SELECT w.* FROM word w WHERE NOT EXISTS(
SELECT NULL FROM translation t WHERE t.WordID = 1
) AND NOT EXISTS (
SELECT NULL FROM namespace n WHERE n.IdentifierID = 1
)
編集 #3表の単語には、テーブルの名前空間と翻訳の各行に関連付けられている単語が含まれています。つまり、名前空間と変換テーブルの両方の 1 つまたは複数の行に関連付けられている可能性があります。これは本来、データの重複を防ぎ、検索性能を向上させるために考えられた手段です。
名前空間と変換テーブルの両方でデータ行の更新と非推奨を数か月にわたって行った結果、使用されなくなった単語があります。これらの単語を削除して、スペースを解放し、より関連性の高い検索結果を提供したいと考えています。
編集#4これはタイムアウトエラーかもしれないと思い始めていますか?クエリを次のように変更しようとしました。
DELETE FROM word WHERE KeyID NOT IN (
SELECT WordID FROM translation
UNION
SELECT IdentifierID FROM namespace
)
役立たず。
インデックスに関しては、説明すると次の結果が得られます
id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
'1', 'PRIMARY', 'word', 'ALL', NULL, NULL, NULL, NULL, '18430', 'Using where'
'2', 'DEPENDENT SUBQUERY', 'translation', 'ALL', NULL, NULL, NULL, NULL, '28219', 'Using where'
'3', 'DEPENDENT UNION', 'namespace', 'ALL', NULL, NULL, NULL, NULL, '7708', 'Using where'
NULL, 'UNION RESULT', '<union2,3>', 'ALL', NULL, NULL, NULL, NULL, NULL, ''
word : KeyIDの主キーとKey列のインデックス キー。
translation : TranslationIDの主キーとインデックス キーNamespaceIDKey
namespace : NamespaceIDの主キー
編集#5私が尋ねた質問に必ずしも答えるとは限りませんが、次のブルートフォースクエリで問題が解決しました。ただし、データベースに外部キーがある場合、このアプローチは明らかに機能しませんが、それでも次のようになります。
-- Push all relevant words into a temporary table
CREATE TABLE temp
SELECT DISTINCT w.* FROM translation t
INNER JOIN word w ON w.KeyID = t.WordID
UNION
SELECT w2.* FROM namespace n2
INNER JOIN word w2 ON w2.KeyID = n2.IdentifierID;
-- Empty the table
TRUNCATE TABLE word;
-- Re-insert the relevant words
INSERT INTO word
SELECT * FROM temp;