删除 Mysql 后对索引 table 性能的影响
Impact on performance on an Indexed table after deletion Mysql
我有一个包含 100 亿行的 table,我的搜索查询提取了 150 万行已编入索引。我的问题是,如果我删除不必要的行并减少到 300 万行,我想我的搜索条件性能会提高。这是我的问题
- 如果我使用 100 亿行和 300 万行查询相同数量的数据,索引如何工作
这是我的 Table 详细信息和简单的搜索查询。 @startdate 是一个输入,它总是一个月
CREATE TABLE `ABCD` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT,
`VAL` varchar(255) DEFAULT NULL,
`NVAL` varchar(255) DEFAULT NULL,
`DOC` bigint(20) NOT NULL,
`DESC` int(11) NOT NULL,
`DateCreat` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`ID`),
KEY `IDX_DOC` (`DOC`), -- BTREE NON-UNIQUE
KEY `INDEX_DESC` (`DESC`), -- BTREE NON-UNIQUE
KEY `INDEX_DateCreat` (`DateCreat`) -- BTREE NON-UNIQUE
) ENGINE=InnoDB AUTO_INCREMENT=14755842749 DEFAULT CHARSET=utf8
SELECT
MONTH(@START_DATE) 'Month'
,count(distinct DOC) 'Docs'
FROM
ABCD USE INDEX (IDX_DOC, INDEX_DateCreat)
WHERE
DateCreat >= @START_DATE and DateCreat < @END_DATE
(评论太长了。)
视情况而定。在某些情况下不会有任何改善;在某些方面,会有显着改善。
请提供 SHOW CREATE TABLE
和样本 DELETE
和 SELECT
。
'search' 是如何完成的 -- 通过 PRIMARY KEY
?副键?非索引列?
删除的行是否在 table 的一个“末端”(例如清除“旧”数据)?还是分散?
您如何处理返回的 150 万行? (很多!)
索引是如何工作的。从阅读维基百科中的 B+ 树开始。或者您正在使用 FULLTEXT
?或者 SPATIAL
?
加速
你不想 GROUP BY MONTH(DateCreat)
和 SELECT MONTH(DateCreat)
吗?还是您真的要显示一系列月份,但仅将它们标记为一个月?
无论如何,如果你有一个摘要 table——也许是一天——你可以非常有效地总结摘要 table 中的计数以非常快速地获取 COUNT
.
重新索引
我仍然需要知道您是要删除“旧”行还是分散在 'months' 中的行。
如果您要删除“旧”行,那么 PARTITIONing
会更有效率。更多详情:http://mysql.rjweb.org/doc.php/partitionmaint
如果您要删除分散在 table 中的行,让我们进入 BTrees。数据将按 PK 排序。那是 id
,这可能是按时间顺序排列的(或至少大约如此)。
数据存储在块中,每个块可能有 100 行,如果这些 varchars 包含“短”字符串,则可能更多。一个块是16KB.
当您删除 scattered 行时,您将减少某些块中的行数,但不会减少块数。 (OK,如果相邻的两个block足够稀疏,就合并在一起。)
查询的速度达到巨大 table(太大而无法缓存在 ram 中)主要取决于 块 接触的数量。
所以,DELETE
对这个查询的性能没有多大帮助。
更好的指数
对于这个查询,将INDEX(doc)
替换为INDEX(doc, date_creat)
或将INDEX(date_creat)
替换为INDEX(date_creat, doc)
会加速查询,甚至在任何删除之前。 (两个索引都可以改,但是可能会花很长时间。)
每个二级索引都是一个BTree。这个 BTree 可能会发生类似于我上面提到的删除过程中的变化。也就是说,删除一些文档可能会从第一个索引中删除块,或者删除“旧”行很可能会删除第二个索引的一大块。同时,另一个索引的密度将大大降低。
那些建议的索引正在“覆盖”。这意味着可以使用 only 和 INDEX
.
来执行查询
指数效率
我不得不再次说“这取决于”...
根据经验,如果要使用超过 20% 的索引,则将忽略该索引。也就是说,如果 WHERE DateCreat >= @START_DATE and DateCreat < @END_DATE
是一个 小 日期范围,则将考虑以 DateCreat
开头的任何索引 。对于大范围,将忽略索引并使用 table。
最佳总结
更大的日期范围:INDEX(date_creat, doc)
-- 过滤将发生和覆盖。没有它,将扫描整个 table;在这种情况下,table 中的块数很关键——因此,回到删除所做或未做的事情。
较小的日期范围:INDEX(date_creat, doc)
最好,但 ``INDEX(date_creat)` 次之。 Delete 影响较小,但现在需要在 BTree(数据和索引)中都考虑影响。
我有一个包含 100 亿行的 table,我的搜索查询提取了 150 万行已编入索引。我的问题是,如果我删除不必要的行并减少到 300 万行,我想我的搜索条件性能会提高。这是我的问题
- 如果我使用 100 亿行和 300 万行查询相同数量的数据,索引如何工作
这是我的 Table 详细信息和简单的搜索查询。 @startdate 是一个输入,它总是一个月
CREATE TABLE `ABCD` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT,
`VAL` varchar(255) DEFAULT NULL,
`NVAL` varchar(255) DEFAULT NULL,
`DOC` bigint(20) NOT NULL,
`DESC` int(11) NOT NULL,
`DateCreat` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`ID`),
KEY `IDX_DOC` (`DOC`), -- BTREE NON-UNIQUE
KEY `INDEX_DESC` (`DESC`), -- BTREE NON-UNIQUE
KEY `INDEX_DateCreat` (`DateCreat`) -- BTREE NON-UNIQUE
) ENGINE=InnoDB AUTO_INCREMENT=14755842749 DEFAULT CHARSET=utf8
SELECT
MONTH(@START_DATE) 'Month'
,count(distinct DOC) 'Docs'
FROM
ABCD USE INDEX (IDX_DOC, INDEX_DateCreat)
WHERE
DateCreat >= @START_DATE and DateCreat < @END_DATE
(评论太长了。)
视情况而定。在某些情况下不会有任何改善;在某些方面,会有显着改善。
请提供 SHOW CREATE TABLE
和样本 DELETE
和 SELECT
。
'search' 是如何完成的 -- 通过 PRIMARY KEY
?副键?非索引列?
删除的行是否在 table 的一个“末端”(例如清除“旧”数据)?还是分散?
您如何处理返回的 150 万行? (很多!)
索引是如何工作的。从阅读维基百科中的 B+ 树开始。或者您正在使用 FULLTEXT
?或者 SPATIAL
?
加速
你不想 GROUP BY MONTH(DateCreat)
和 SELECT MONTH(DateCreat)
吗?还是您真的要显示一系列月份,但仅将它们标记为一个月?
无论如何,如果你有一个摘要 table——也许是一天——你可以非常有效地总结摘要 table 中的计数以非常快速地获取 COUNT
.
重新索引
我仍然需要知道您是要删除“旧”行还是分散在 'months' 中的行。
如果您要删除“旧”行,那么 PARTITIONing
会更有效率。更多详情:http://mysql.rjweb.org/doc.php/partitionmaint
如果您要删除分散在 table 中的行,让我们进入 BTrees。数据将按 PK 排序。那是 id
,这可能是按时间顺序排列的(或至少大约如此)。
数据存储在块中,每个块可能有 100 行,如果这些 varchars 包含“短”字符串,则可能更多。一个块是16KB.
当您删除 scattered 行时,您将减少某些块中的行数,但不会减少块数。 (OK,如果相邻的两个block足够稀疏,就合并在一起。)
查询的速度达到巨大 table(太大而无法缓存在 ram 中)主要取决于 块 接触的数量。
所以,DELETE
对这个查询的性能没有多大帮助。
更好的指数
对于这个查询,将INDEX(doc)
替换为INDEX(doc, date_creat)
或将INDEX(date_creat)
替换为INDEX(date_creat, doc)
会加速查询,甚至在任何删除之前。 (两个索引都可以改,但是可能会花很长时间。)
每个二级索引都是一个BTree。这个 BTree 可能会发生类似于我上面提到的删除过程中的变化。也就是说,删除一些文档可能会从第一个索引中删除块,或者删除“旧”行很可能会删除第二个索引的一大块。同时,另一个索引的密度将大大降低。
那些建议的索引正在“覆盖”。这意味着可以使用 only 和 INDEX
.
指数效率
我不得不再次说“这取决于”...
根据经验,如果要使用超过 20% 的索引,则将忽略该索引。也就是说,如果 WHERE DateCreat >= @START_DATE and DateCreat < @END_DATE
是一个 小 日期范围,则将考虑以 DateCreat
开头的任何索引 。对于大范围,将忽略索引并使用 table。
最佳总结
更大的日期范围:INDEX(date_creat, doc)
-- 过滤将发生和覆盖。没有它,将扫描整个 table;在这种情况下,table 中的块数很关键——因此,回到删除所做或未做的事情。
较小的日期范围:INDEX(date_creat, doc)
最好,但 ``INDEX(date_creat)` 次之。 Delete 影响较小,但现在需要在 BTree(数据和索引)中都考虑影响。