簡體   English   中英

如何使用 Mysql 的范圍優化查詢

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM