非常感谢你的帮助!我试图打破我的问题:
背景
我试图了解我们的文件服务器如何随着时间的推移而增长,我想通过收集使用数据和运行统计信息(用户所需的空间,最大的目录,增长最快的目录等)来实现这一点。 / p>
为了收集一个快照,我编写了一个脚本,该脚本遍历目录树并使用以下标题将数据写入CSV文件:
SCANID,SCANDATE,DIR,FILENAME,SIZE,MODTIME,ATIME,OWNER
SCANID:随机uuid4字符串标识扫描
SCANDATE:扫描开始的日期(不一定是与SCANID的1:1关系)
挑战
我可以将它导入到MySQL中的等效表中,但我很快就遇到了性能问题。我们的系统上有数百万个文件。 MySQL表如下:
CREATE TABLE IF NOT EXISTS FILES (
SCANID VARCHAR(40),
SCANDATE DATE,
DIRECTORY VARCHAR(700),
FILENAME VARCHAR(300),
SIZE BIGINT,
ATIME DATETIME,
MODTIME DATETIME,
OWNER VARCHAR(50)
);
我相信DIRECTORY和FILENAME占用了很大一部分空间,特别是如果你为我的每次扫描都不断重复这些空间。
我想对数据做的分析如下:
*所需磁盘总空间随时间增长的速度有多快
*哪个用户占用的空间最多 - SELECT OWNER, SUM(SIZE) FROM FILES GROUP BY OWNER ORDER BY SUM(SIZE) DESC;
*哪些目录随时间增长最快
*哪些用户随着时间的推移生成大部分数据
解决方法
创建三个表,只收集更改的数据(我只想知道尺寸是否发生变化,只保留最新的所有者,adate和mdate)
表1:FILES
CREATE TABLE IF NOT EXISTS FILES (
SCAN_ID INT,
DIR VARCHAR(700) DEFAULT NULL,
FILENAME VARCHAR(500) DEFAULT NULL,
ATIME DATETIME DEFAULT NULL,
MODTIME DATETIME DEFAULT NULL,
OWNER VARCHAR(50) DEFAULT NULL,
PRIMARY KEY (DIR, FNAME)
);
表2:尺寸
SCAN_ID,FILE_ID,SIZE
表3:SCANDATES
SCAN_ID,SCANDATE
为了实现这一目标,我将完整的CSV文件加载到与CSV文件具有相同结构的临时表(FILES_IMPORT)中,然后将日期分发到相应的表中。
因此,表1应该包含我见过的所有文件名:
INSERT INTO FILES (DIR, FNAME, OWNER, ATIME, MODTIME)
SELECT DIR, FNAME, OWNER, ATIME, MODTIME FROM FILES_IMPORT
ON DUPLICATE KEY UPDATE
OWNER=VALUES(OWNER),
ATIME=VALUES(ATIME),
MODTIME=VALUES(MODTIME);
As(DIR,FILENAME)是主键,这满足了每个文件只有一个条目的要求。
问题
但是,我不知道如何更新SIZES表。我不希望将(DIR,FNAME)作为PRIMARY KEY,因为这不会使DB更小或更快。除此之外,我不知道我的方法是否合理。
非常感谢你的帮助。
答案 0 :(得分:1)
我只想写一些没有特别顺序的想法。
您尚未描述针对此数据运行的任何特定SQL查询,因此我们无法制定有关索引或其他优化的策略。这些很重要,而且通常比数据的大小更重要。
如果您正在执行需要扫描所有行的复杂报表查询,则可能需要使用面向列的存储引擎来获得更好的性能。同样,这取决于您需要优化的查询类型。
我不知道为什么你有SCAN_ID(4个字节),因为它有1:1的关系(顺便说一下,请不要使用术语“{{ 3}}“当你的意思是”关系“)。如果您不使用SCAN_ID,则可以使用SCAN_DATE,FILE_ID作为SIZES表的主键。
您可以使用文件3 bytes作为文件的主键。虽然inode编号在不同的文件系统上是独立编号的,但如果你的服务器安装了多个文件系统,你也必须在主键中包含一些文件系统的标识符。