[英]How to optimize a query using a range with Mysql
我嘗試優化此查詢:
select id_store from receipt where receiptDate between '20151109' and '20151116'
我使用命令EXPLAIN
執行此查詢。 似乎沒有使用密鑰。 未使用receiptDate 的索引。 怎么了 ?
這是表receipt
的結構:
CREATE TABLE receipt (
id_store tinyint(3) unsigned NOT NULL default '0',
id_receipt int(7) unsigned NOT NULL default '0',
id_product smallint(6) unsigned NOT NULL default '0',
receiptDate char(8) NOT NULL default '',
qty float NOT NULL default '0',
turnover float NOT NULL default '0',
PRIMARY KEY (id_store,id_receipt,id_product,receiptDate),
KEY NDX_1 (receiptDate),
) ENGINE=MEMORY;
這是命令EXPLAIN
的結果:
+----+-------------+---------------------+--------+-----------------------------------------------------------+---------------------------------+---------+--------------------------------------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------------+--------+-----------------------------------------------------------+---------------------------------+---------+--------------------------------------+------+---------------------------------+
| 1 | SIMPLE | receipt | ALL |NDX_1 | | | |24789225| Using where |
+----+-------------+---------------------+--------+-----------------------------------------------------------+---------------------------------+---------+--------------------------------------+------+---------------------------------+
表receipt
包含 24.789.225 行,平均每天 15.000 行 (receiptDate)。 我執行以下查詢並獲得 120.295 行:
select count(*) from receipt where receiptDate between '20151109' and '20151116'
在此先感謝您的幫助。
由於您索引了receiptDate
,如果優化器認為它會提高性能,數據庫引擎將使用該索引。 優化器根據有關表的統計信息做出決定。 它在后台創建這些統計信息,這是一個非常透明的過程。
現在您正在使用MEMORY
引擎。 因為內存表應該是短暫的,所以這些特殊引擎的優化器功能非常有限。 您可能希望強制查詢使用帶有FORCE INDEX
關鍵字的FORCE INDEX
。
您的日期存儲為CHAR(8)
,這很慢,因為引擎必須解析所有高度CHAR
。 您將通過INT
獲得改進的性能(將日期轉換為YYYYMMDD
)。 您的查詢應該仍然有效,因為引擎會自動將字符串輸入轉換為 int。
如果你打算使用InnoDB
引擎,那么你應該盡可能把日期作為主鍵,因為主鍵也是這個引擎的Clustered Index
,這意味着數據將在存儲上按日期物理排序。
使用 3 字節DATE
數據類型receiptDate
用於receiptDate
的 8 字節(如果 utf8 則為 24 字節)CHAR(8)。
當您使用它時,如果它只有 7 位數字,您可以通過使id_receipt
MEDIUMINT UNSIGNED
來節省另一個字節。
指定 BTREE:
KEY `NDX_1` (`receiptDate`) USING BTREE
因為MEMORY
可能使它成為HASH
索引。 BTREE
可以處理范圍; HASH
必須做一個表掃描。
我同意 InnoDB 整體上可能會更好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.