我尝试优化此查询:
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'
提前感谢您的帮助。
答案 0 :(得分:0)
自索引receiptDate
以来,如果优化程序认为,数据库引擎将使用此索引,它将提高性能。优化程序根据有关表的统计信息做出决策。它在后台创建这些统计信息,这是一个大多数透明的过程。
现在您正在使用MEMORY
引擎。因为内存表应该是短暂的,所以这些特殊的引擎具有非常有限的优化器功能。您可能希望强制查询使用带有FORCE INDEX
关键字的索引。
您的日期存储为CHAR(8)
,这很慢,因为引擎必须解析所有高度CHAR
。您将使用INT
获得改进的效果(将日期转换为YYYYMMDD
)。您的查询仍然有效,因为引擎会自动将字符串输入转换为int。
如果您打算使用InnoDB
引擎,那么您应该尽可能将日期作为主键,因为主键也是带有此引擎的Clustered Index
,这意味着数据将会按存储上的日期进行物理分类。
答案 1 :(得分:0)
使用3字节receiptDate
数据类型,而不是DATE
的8字节(或utf8为24字节)CHAR(8)。
当你在这里时,如果它只有7位,你可以通过id_receipt
MEDIUMINT UNSIGNED
来保存另一个字节。
指定BTREE:
KEY `NDX_1` (`receiptDate`) USING BTREE
因为MEMORY
可能会使其成为HASH
索引。 BTREE
可以处理范围; HASH
必须进行表扫描。
我同意InnoDB总体上可能更好。