diff --git a/src/services/drive/add-file.ts b/src/services/drive/add-file.ts
index 830f5e0431..77ee70db55 100644
--- a/src/services/drive/add-file.ts
+++ b/src/services/drive/add-file.ts
@@ -17,7 +17,7 @@ import { isLocalUser, IUser, IRemoteUser } from '../../models/user';
 import delFile from './delete-file';
 import config from '../../config';
 import { getDriveFileThumbnailBucket } from '../../models/drive-file-thumbnail';
-import { driveStats } from '../stats';
+import { driveStats, perUserDriveStats } from '../stats';
 
 const log = debug('misskey:drive:add-file');
 
@@ -394,6 +394,7 @@ export default async function(
 
 	// 統計を更新
 	driveStats.update(driveFile, true);
+	perUserDriveStats.update(driveFile, true);
 
 	return driveFile;
 }
diff --git a/src/services/drive/delete-file.ts b/src/services/drive/delete-file.ts
index e6aa1a0649..761a5d6d4f 100644
--- a/src/services/drive/delete-file.ts
+++ b/src/services/drive/delete-file.ts
@@ -2,7 +2,7 @@ import * as Minio from 'minio';
 import DriveFile, { DriveFileChunk, IDriveFile } from '../../models/drive-file';
 import DriveFileThumbnail, { DriveFileThumbnailChunk } from '../../models/drive-file-thumbnail';
 import config from '../../config';
-import { driveStats } from '../stats';
+import { driveStats, perUserDriveStats } from '../stats';
 
 export default async function(file: IDriveFile, isExpired = false) {
 	if (file.metadata.storage == 'minio') {
@@ -49,4 +49,5 @@ export default async function(file: IDriveFile, isExpired = false) {
 
 	// 統計を更新
 	driveStats.update(file, false);
+	perUserDriveStats.update(file, false);
 }
diff --git a/src/services/stats.ts b/src/services/stats.ts
index 2a2dc848a3..558e1786d4 100644
--- a/src/services/stats.ts
+++ b/src/services/stats.ts
@@ -911,3 +911,103 @@ class PerUserNotesStats extends Stats<PerUserNotesLog> {
 
 export const perUserNotesStats = new PerUserNotesStats();
 //#endregion
+
+//#region Per user drive stats
+/**
+ * ユーザーごとのドライブに関する統計
+ */
+type PerUserDriveLog = {
+	/**
+	 * 集計期間時点での、全ドライブファイル数
+	 */
+	totalCount: number;
+
+	/**
+	 * 集計期間時点での、全ドライブファイルの合計サイズ
+	 */
+	totalSize: number;
+
+	/**
+	 * 増加したドライブファイル数
+	 */
+	incCount: number;
+
+	/**
+	 * 増加したドライブ使用量
+	 */
+	incSize: number;
+
+	/**
+	 * 減少したドライブファイル数
+	 */
+	decCount: number;
+
+	/**
+	 * 減少したドライブ使用量
+	 */
+	decSize: number;
+};
+
+class PerUserDriveStats extends Stats<PerUserDriveLog> {
+	constructor() {
+		super('perUserDrive', true);
+	}
+
+	@autobind
+	protected async getTemplate(init: boolean, latest?: PerUserDriveLog, group?: any): Promise<PerUserDriveLog> {
+		const calcSize = () => DriveFile
+			.aggregate([{
+				$match: {
+					'metadata.userId': group,
+					'metadata.deletedAt': { $exists: false }
+				}
+			}, {
+				$project: {
+					length: true
+				}
+			}, {
+				$group: {
+					_id: null,
+					usage: { $sum: '$length' }
+				}
+			}])
+			.then(res => res.length > 0 ? res[0].usage : 0);
+
+		const [count, size] = init ? await Promise.all([
+			DriveFile.count({ 'metadata.userId': group }),
+			calcSize()
+		]) : [
+			latest ? latest.totalCount : 0,
+			latest ? latest.totalSize : 0
+		];
+
+		return {
+			totalCount: count,
+			totalSize: size,
+			incCount: 0,
+			incSize: 0,
+			decCount: 0,
+			decSize: 0
+		};
+	}
+
+	@autobind
+	public async update(file: IDriveFile, isAdditional: boolean) {
+		const update: Obj = {};
+
+		update.totalCount = isAdditional ? 1 : -1;
+		update.totalSize = isAdditional ? file.length : -file.length;
+		if (isAdditional) {
+			update.incCount = 1;
+			update.incSize = file.length;
+		} else {
+			update.decCount = 1;
+			update.decSize = file.length;
+		}
+
+		await this.inc(update, file.metadata.userId);
+	}
+}
+
+export const perUserDriveStats = new PerUserDriveStats();
+//#endregion