如何使用Mysql

时间:2015-11-20 10:34:27

标签: mysql optimization range

我尝试优化此查询:

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'

提前感谢您的帮助。

2 个答案:

答案 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总体上可能更好。