use*_*770 5 mysql innodb index mysql-5.6
现在有两种方法可以在 MySQL 中构建表的索引:
在第一个过程中,我们将拥有连续的数据(所有字段)页面,然后是索引页面。所以当我们使用索引查询时,MySQL 必须首先加载索引页并找出匹配的键,并且必须在数据页上查找那些主键。为此,它必须再次加载数据页以获取数据。当我们有更大的索引扫描时这很有用,因为我们所有的索引都是连续加载的。
在索引创建的第二种方式中,过滤后的索引页很可能包含与它们同时创建的靠近它的数据页。所以我想小范围扫描的查找速度会更快。
我的理解正确吗?
更新:
我应该在第一种导入数据的方式中提到“PRIMARY KEY 已启用”(自动递增 id 列)。因此,不会生成内部 rowid,并且由于我们不打算添加 PRIMARY KEY,因此会保存大量 IO。
正如您所指出的,当我们使用第二种方法导入数据时会出现碎片。
考虑到我的要求是更大范围的扫描(扫描~100M 行),我想我会采用第一种导入数据的方式。
6 月 8 日 11:30 更新
CREATE TABLE `table_dummy` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`column1` bigint(20) DEFAULT NULL,
`column2` bigint(20) DEFAULT NULL,
`column3` bigint(20) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`column4` tinyint(1) DEFAULT NULL,
`column5` tinyint(4) DEFAULT NULL,
`column6` bigint(20) DEFAULT NULL,
`column6_created_at` datetime DEFAULT NULL,
`column7` int(11) DEFAULT NULL,
`column8` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `twtaccount_id_2` (`column1`,`column2`),
KEY `twtaccount_id` (`column1`,`created_at`,`column5`),
KEY `twt_user_id` (`column3`,`created_at`,`column5`),
KEY `original_status_id` (`column6`,`column3`,`followers_count`)
)
Run Code Online (Sandbox Code Playgroud)
引擎是 INNODB
这个表有大约 800M 的记录,我进行了转储并以两种方式导入它。
方法 1:仅使用主键创建表并导入整个数据。然后我给出了一个alter语句来添加剩余的索引。
方法 2:使用索引创建表并完成转储。这花费了更多的时间。
PS 与通过“方法 2”转储的表的大小相比,通过“方法 1”生成的表的大小要小约 30GB。方法 1 比“方法 2”花费的时间少得多,几乎是速度的两倍。
我主要关心的是当我选择扫描范围广泛的索引(“仅索引扫描”)时表的性能。
第一种方式,你是正确的。这就是为什么我说软的。
InnoDB 有一个聚集索引,内部称为 gen_clust_index。基本上,它是rowid
在幕后为 InnoDB 表创建的索引(或者如果您像我一样来自新泽西州泽西城,则在幕后创建)。这些 rowid 附加到所有二级索引。
PRIMARY KEY
如果组成KEYPRIMARY KEY
的列的宽度PRIMARY
比rowid
.
对于 InnoDB,第二种创建索引的方法更有意义,因为您没有PRIMARY KEY
在幕后交换 的定义。这是您已经提到的好处 ( ) 的补充data page near to it as they were created at the same time
。第一种索引方法在这方面没有任何收获,充其量只是收支平衡。
虽然第二种方法更适合需求(look up will be faster for a small range scans
),但我对您有一个非常强烈的警告:如果您PRIMARY KEY
用已经排序的列数据填充,您很可能最终会遇到一些索引碎片(请参阅我对帖子Oct 26, 2012
How badly does innodb 片段面对有些无序插入?)如果您知道自己正在进行小范围扫描,那么这是一个不错的权衡。
在这种情况下,同样的警告也适用。你将得到一个支离破碎的PRIMARY KEY
. 证明在我对帖子May 01, 2014
Why would the size of MySQL MyISAM table Index (aka MYI file) not match after mysqldump import? 的回答中得到了表达。
要手动证明,请执行以下操作
步骤01:从数据库服务器mysqldump数据
步骤02:将其加载到测试服务器中
运行查询
SELECT IFNULL(ENGINE,'Total') "Storage Engine",
LPAD(CONCAT(FORMAT(DAT/POWER(1024,pw1),2),' ',
SUBSTR(units,pw1*2+1,2)),17,' ') "Data Size",
LPAD(CONCAT(FORMAT(NDX/POWER(1024,pw2),2),' ',
SUBSTR(units,pw2*2+1,2)),17,' ') "Index Size",
LPAD(CONCAT(FORMAT(TBL/POWER(1024,pw3),2),' ',
SUBSTR(units,pw3*2+1,2)),17,' ') "Total Size" FROM
(SELECT ENGINE,DAT,NDX,TBL,IF(px>4,4,px) pw1,
IF(py>4,4,py) pw2,IF(pz>4,4,pz) pw3 FROM
(SELECT *,FLOOR(LOG(IF(DAT=0,1,DAT))/LOG(1024)) px,
FLOOR(LOG(IF(NDX=0,1,NDX))/LOG(1024)) py,
FLOOR(LOG(IF(TBL=0,1,TBL))/LOG(1024)) pz
FROM (SELECT ENGINE,SUM(data_length) DAT,SUM(index_length) NDX,
SUM(data_length+index_length) TBL FROM (SELECT engine,data_length,index_length
FROM information_schema.tables WHERE table_schema NOT IN
('information_schema','performance_schema','mysql') AND ENGINE IS NOT NULL) AAA
GROUP BY ENGINE WITH ROLLUP) AAA ) AA) A,(SELECT ' BKBMBGBTB' units) B;
Run Code Online (Sandbox Code Playgroud)
步骤04:来自测试服务器的mysqldump
步骤05:再次将测试服务器的转储重新加载回测试服务器
步骤 06:运行步骤 03 中的查询
有时,大组数据在重新加载mysql数据时会产生不同的大小
底线:对于 InnoDB,这两种方法都没有比另一种方法有显着优势。
归档时间: |
|
查看次数: |
594 次 |
最近记录: |