bbi*_*ras 4 mysql performance query-performance
当我执行以下操作时,我得到Using where; Using index; Using temporary
. 我该如何摆脱Using temporary
?
http://sqlfiddle.com/#!8/f61a2/3/0
CREATE TABLE `test` (
`a` varchar(45) NOT NULL,
`b` varchar(45) NOT NULL,
`date` date NOT NULL,
PRIMARY KEY (`a`,`b`),
KEY `index1` (`b`,`date`),
KEY `index2` (`b`,`date`,`a`)
) ENGINE=InnoDB;
INSERT INTO test (a, b, date) VALUES ('a1', 'b1', now());
INSERT INTO test (a, b, date) VALUES ('a1', 'b2', now());
INSERT INTO test (a, b, date) VALUES ('a2', 'b1', now());
INSERT INTO test (a, b, date) VALUES ('a2', 'b2', now());
INSERT INTO test (a, b, date) VALUES ('a3', 'b1', '2000-01-01 01:01:01');
INSERT INTO test (a, b, date) VALUES ('a3', 'b2', '2000-01-01 01:01:01');
Run Code Online (Sandbox Code Playgroud)
EXPLAIN SELECT
DISTINCT a
FROM test
WHERE b IN ('b1', 'b2') AND
date > NOW() - INTERVAL 1 MONTH;
Run Code Online (Sandbox Code Playgroud)
您是否有性能问题,因为这听起来像是过早的优化?
使用索引的唯一好的单个查询是 UNION(它也将过滤掉重复项)。
如果您EXPLAIN
在此查询上运行,则说明中不会弹出using 临时..
SELECT
a
FROM test
WHERE b = 'b1' AND
date > NOW() - INTERVAL 1 MONTH
UNION
SELECT
a
FROM test
WHERE b = 'b2' AND
date > NOW() - INTERVAL 1 MONTH
;
Run Code Online (Sandbox Code Playgroud)
已编辑 2019-09-01
演示不再有效,因为sqlfiddle不再运行旧的 MySQL 版本,并且因为 MySQL 源代码已更新...
我建议查看db-fiddle并在 MySQL 版本 5.5/5.6/5.7 之间切换,然后问题应该在 5.5 和 5.6 之间可见
通过查看sql/union.cc
MySQL 5.7.2 m12 版本的源代码文件(C++ 代码)(很可能(所有)较低版本也使用此代码,但不确定),我们可以看到 UNION 在 MySQL 中的工作方式。您会发现EXPLAIN 输出有时会告诉您谎言,因为源代码(在输入参数之一中)表明:
is_union_distinct
如果设置,临时表将在插入时消除重复项
这是有道理的,因为重复的记录被过滤掉了。源代码截图如下:
/*
Create a temporary table to store the result of select_union.
SYNOPSIS
select_union::create_result_table()
thd thread handle
column_types a list of items used to define columns of the
temporary table
is_union_distinct if set, the temporary table will eliminate
duplicates on insert
options create options
table_alias name of the temporary table
bit_fields_as_long convert bit fields to ulonglong
DESCRIPTION
Create a temporary table that is used to store the result of a UNION,
derived table, or a materialized cursor.
RETURN VALUE
0 The table has been created successfully.
1 create_tmp_table failed.
*/
bool
select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
bool is_union_distinct, ulonglong options,
const char *table_alias,
bool bit_fields_as_long, bool create_table)
{
DBUG_ASSERT(table == 0);
tmp_table_param.init();
count_field_types(thd_arg->lex->current_select(), &tmp_table_param,
*column_types, false, true);
tmp_table_param.skip_create_table= !create_table;
tmp_table_param.bit_fields_as_long= bit_fields_as_long;
if (! (table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
(ORDER*) 0, is_union_distinct, 1,
options, HA_POS_ERROR, (char*) table_alias)))
return TRUE;
if (create_table)
{
table->file->extra(HA_EXTRA_WRITE_CACHE);
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
}
return FALSE;
}
Run Code Online (Sandbox Code Playgroud)
有一个函数被调用create_tmp_table
,因此MySQL总是在create_result_table
调用该函数时创建一个临时表。
归档时间: |
|
查看次数: |
5128 次 |
最近记录: |