我們有一個分析產品。對於我們的每個客戶,我們提供一個JavaScript代碼,他們將這些代碼放入他們的網站。如果用戶訪問我們的客戶站點,Java腳本代碼會打到我們的服務器,以便我們代表此客戶存儲此頁面訪問。每個客戶都包含唯一的域名。MySql - 處理表格大小和性能
我們正在MySql表中存儲此頁訪問。
以下是表格模式。
CREATE TABLE `page_visits` (
`domain` varchar(50) DEFAULT NULL,
`guid` varchar(100) DEFAULT NULL,
`sid` varchar(100) DEFAULT NULL,
`url` varchar(2500) DEFAULT NULL,
`ip` varchar(20) DEFAULT NULL,
`is_new` varchar(20) DEFAULT NULL,
`ref` varchar(2500) DEFAULT NULL,
`user_agent` varchar(255) DEFAULT NULL,
`stats_time` datetime DEFAULT NULL,
`country` varchar(50) DEFAULT NULL,
`region` varchar(50) DEFAULT NULL,
`city` varchar(50) DEFAULT NULL,
`city_lat_long` varchar(50) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
KEY `sid_index` (`sid`) USING BTREE,
KEY `domain_index` (`domain`),
KEY `email_index` (`email`),
KEY `stats_time_index` (`stats_time`),
KEY `domain_statstime` (`domain`,`stats_time`),
KEY `domain_email` (`domain`,`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
我們沒有此表的主鍵。
MySQL服務器的細節
這是谷歌雲的MySQL(版本5.6)和存儲容量10TB是。
截至目前,我們的桌子上有3.5億行,桌子的尺寸是300 GB。即使一個客戶與另一個客戶之間沒有關係,我們仍將所有客戶詳細信息存儲在同一個表中。
問題1:對於少數客戶在表中有大量行的情況,對這些客戶的查詢性能非常低。
實例查詢1:
SELECT count(DISTINCT sid) AS count,count(sid) AS total FROM page_views WHERE domain = 'aaa' AND stats_time BETWEEN CONVERT_TZ('2015-02-05 00:00:00','+05:30','+00:00') AND CONVERT_TZ('2016-01-01 23:59:59','+05:30','+00:00');
+---------+---------+
| count | total |
+---------+---------+
| 1056546 | 2713729 |
+---------+---------+
1 row in set (13 min 19.71 sec)
我會在這裏更新更多的查詢。我們需要5-10秒以內的結果,有可能嗎?
問題2:表格大小正在迅速增加,我們可能會在今年年底達到5 TB的表格大小,所以我們想要分割表格。我們希望在一臺機器上保留與一個客戶有關的所有記錄。這個分片的最佳實踐是什麼?
我們正在考慮針對上述問題的方法,請爲我們提供解決這些問題的最佳實踐。
爲每個客戶
1)如果我們爲每個客戶建立單獨的表有什麼優點和缺點創建單獨的表。截至目前,我們有3萬個客戶,到今年年底可能達到10萬,這意味着數據庫中有10萬個表。我們同時訪問所有表以進行讀取和寫入。
2)我們會去同一個表中,將創建基於日期範圍
UPDATE分區:一個「客戶」由域確定的? 答案是肯定的
感謝
@詹姆斯感謝您的詳細解釋,你能分享任何解釋爲什麼100k表不是一個好的決定。 – Rams
真棒迴應。豐富的信息。 – cloudpre
100K表是這個論壇上的常見問題。以下是一些反對它的論點:操作系統開銷和放緩;代碼中的複雜性;很少優勢。可能會有很多小桌子和一些大桌子 - 每個極端都有它自己的低效率。 –