如何在 MySQL 中使用 LAST_DAY() 以便不丢失索引优势?
How to use LAST_DAY() in MySQL so index advantage is not lost?
我正在使用 MySQL tables。
示例 table EMP
(primary_key
在 (EID, DOJ)
上):
ENAME
EID
DEPT
SAL
DOJ (YYYY-MM-DD)
A
6
ee
2000
2021-03-01
B
5
me
2020
2021-04-30
C
3
it
2000
2020-12-27
D
4
cv
2020
2020-10-31
E
1
it
2000
2021-01-01
F
2
it
null
2021-02-28
G
7
ee
null
2020-11-20
我有一项工作是将数据删除和插入到类似结构的 table。
进程需要删除非每月数据。也就是说,它将删除带有 EID
的行
6, 3, 1, 7
:这些行有 DOJ
不是 月末。
我提出的查询:
-- DOJ is of type DATE
DELETE FROM EMP WHERE LAST_DAY(DOJ) <> DOJ ;
它按预期工作。但是,因为有大量数据(~500 万),所以速度很慢。
我明白因为 LAST_DAY()
功能,我 loosing index
优势 DOJ
。
您能否建议我如何改进查询?
Where (month(doj) in (9,4,6,11) and day(doj) <> 30) or
(month(doj) in (1,3,5,7,8,10,12) and day(doj) <> 31) or
(month(doj) in (2) and day(doj) not in(28,29))
?你可以稍微调整一下二月
关于索引,你是对的。在这里没有用。想到的唯一想法是生成一个列来告诉您日期是否是月底。因此,您将拥有一个可以索引并在查询中使用的列:
create table emp
(
ename varchar(100),
...
doj date,
is_month_end bool as (doj = last_day(doj))
);
create index idx_month_ends on emp (is_month_end);
delete from emp where not is_month_end;
演示:https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=397388b70bb1f459bbefce630ad27ac4
索引只能提供帮助,但是,如果这只是 table 中数据的很小一部分,比如说 1%。要删除更多行,阅读整个 table.
更有意义
我正在使用 MySQL tables。
示例 table EMP
(primary_key
在 (EID, DOJ)
上):
ENAME | EID | DEPT | SAL | DOJ (YYYY-MM-DD) |
---|---|---|---|---|
A | 6 | ee | 2000 | 2021-03-01 |
B | 5 | me | 2020 | 2021-04-30 |
C | 3 | it | 2000 | 2020-12-27 |
D | 4 | cv | 2020 | 2020-10-31 |
E | 1 | it | 2000 | 2021-01-01 |
F | 2 | it | null | 2021-02-28 |
G | 7 | ee | null | 2020-11-20 |
我有一项工作是将数据删除和插入到类似结构的 table。
进程需要删除非每月数据。也就是说,它将删除带有 EID
的行
6, 3, 1, 7
:这些行有 DOJ
不是 月末。
我提出的查询:
-- DOJ is of type DATE
DELETE FROM EMP WHERE LAST_DAY(DOJ) <> DOJ ;
它按预期工作。但是,因为有大量数据(~500 万),所以速度很慢。
我明白因为 LAST_DAY()
功能,我 loosing index
优势 DOJ
。
您能否建议我如何改进查询?
Where (month(doj) in (9,4,6,11) and day(doj) <> 30) or
(month(doj) in (1,3,5,7,8,10,12) and day(doj) <> 31) or
(month(doj) in (2) and day(doj) not in(28,29))
?你可以稍微调整一下二月
关于索引,你是对的。在这里没有用。想到的唯一想法是生成一个列来告诉您日期是否是月底。因此,您将拥有一个可以索引并在查询中使用的列:
create table emp
(
ename varchar(100),
...
doj date,
is_month_end bool as (doj = last_day(doj))
);
create index idx_month_ends on emp (is_month_end);
delete from emp where not is_month_end;
演示:https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=397388b70bb1f459bbefce630ad27ac4
索引只能提供帮助,但是,如果这只是 table 中数据的很小一部分,比如说 1%。要删除更多行,阅读整个 table.
更有意义