-- 表結構:appkey VARCHAR(20) 主鍵第一列 -- 錯誤寫法(無引號) EXPLAIN SELECT * FROM appstat_day_prototype_201305 WHERE appkey = xxxxx AND day_key BETWEEN '2013-05-23' AND '2013-05-30'; -- type=ALL, rows=19,285,787 全表掃描! -- 正確寫法(加引號) EXPLAIN SELECT * FROM appstat_day_prototype_201305 WHERE appkey = 'xxxxx' AND day_key BETWEEN '2013-05-23' AND '2013-05-30'; -- type=range, rows=1 索引生效!
-- 表結構:poll_id BIGINT 有索引 SELECT * FROM poll_joined_151 WHERE poll_id = '2348993' AND anonymous = 0 ORDER BY add_time DESC LIMIT 3; -- type=ref, rows=30,240 用到索引,但掃描行數較多
若比較雙方類型不一致,MySQL 會將雙方**統一轉為浮點數(DOUBLE)**再比較。
字符串轉浮點數規則:從左到右讀取數字字符,遇非數字停止。
'1',' 1','1a'→ 均轉為1.0
索引存儲的是原始字符串 '1', ' 1', '1a'。轉浮點數後均為 1.0,MySQL 無法利用索引有序性,只能全表掃描逐行轉換比較。
純數字字符串 '2348993' → 浮點數 2348993.0,與索引值一一對應,順序不變,故可走索引(但仍有 CPU 轉換開銷)。
SELECT CAST(' 1' AS SIGNED) = 1; -- 1 (true)
SELECT CAST(' 1a' AS SIGNED) = 1; -- 1 (true) + Warning
SELECT CAST('1' AS SIGNED) = 1; -- 1 (true)
DOUBLE 只有 53 位有效二進制位(≈15~16 位十進制)。超大整數比較會失真:
SELECT 9223372036854775807 = 9223372036854775808; -- 1 (true!) 精度丟失
long_query_time + log_queries_not_using_indexes 捕獲隱式轉換慢查詢一個引號的缺失,可能拖垮整個數據庫。類型安全,從寫 SQL 那一刻開始。