如果我有这个400M行表:
create table my_table
( id int,
filled tinyint,
content text not null
) engine=myisam
我可以通过以下方式阻止对内容的额外访问(由于列类型的文本):
select id,if(filled,content,'') from my_table
(填充的是0还是1)?
或者,如果content可以为null,则将
select id,ifnull(content,'') from my_table
会更好(仍会在性能方面,因为会发生空开销)?
您的问题不准确。可能会连续filled = 1
和content = 'some text'
?
如果是,则IF(filled, content, '')
有意义。
如果否,则摆脱掉filled
并简单地设置content
为''
。访问空字符串的成本content
很小。
content
通常多大?如果通常只有数百个字符,则性能差异很小。
不要使用MyISAM,请切换到InnoDB。
你有很多的DELETEs
还是UPDATEs
?如果是这样,则MyISAM的.MYD文件可能会碎片化。这意味着content
可能分散在磁盘周围。如果您没有更新或删除,则content
“就在那里”,因此实际上可以自由访问。
相反,InnoDB有时会放下TEXT
并BLOB
“关闭记录”。
但是,哪个更好或更坏?离记录(在某些情况下)与碎片(在某些情况下)相比。
您只取一行吗?还是很多这样的行?这是MyISAM和InnoDB实施方式完全不同的另一个领域。MyISAM需要逐步content
进入“下一个”行。(我不会去到一个漫长的讨论,其中“下一个”行很可能是。)
底线:不担心优化,但做改变InnoDB的(对于很多原因)。
“下一个”行可能在哪里?
MyISAM ...按插入顺序将行添加到.MYD。但是,在更新或删除后,新行/已更改的行往往会首先填补空白,而作为最后的选择则将其追加到文件中。
InnoDB ...行在B + Tree中,由排序PRIMARY KEY
。BTree被16KB的块阻塞。您有一TEXT
列,因此变得更加复杂...
对于“小的” TEXT列,几行可容纳16KB。如果content
是1KB的字符串,则最多可将15行放在一个块中。如果它们更大,content
则将被“记录外”存储。
块中的行基本上彼此等距。(最大的工作是将块加载到缓存中并找到该块。)
“下一个”(或“上一个”)块仅是磁盘访问权限-参见“ B + Tree”中的“ +”。
当一个块溢出时,它被“拆分”为两个块,每个块都有一些行。新块分配在某个地方,很少相邻。
使用SSD时,所有块彼此“等距”。使用HDD时,旋转延迟和手臂运动会使该模块的时序比其他模块“更近”。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句