當對數據表進行水平分表之后,若要進行數據統計,往往需要對所有分表一起進行聯合查詢。在使用 Laravel 框架時,可以利用 Model 類的 setTable 方法對於多個表進行合並查詢。
舉個例子,假設 users 表水平拆分為 16 個表,users_0、users_1、users_2……一直到 users_f,這幾個表都有相同的結構,使用 SQL 的 UNION ALL 合並查詢所有表的結果集,然后調用 Model 類的 setTable 方法,把結果集的別名賦值給 Model 類的 table 屬性,這樣就能夠對 users 所有表進行聯合查詢操作了。具體請參考下這篇文章的例子。
<?php class User extends Model { public function setUnionAllTable() { $sql =<<<'EOT' SELECT * FROM users_0 UNION ALL SELECT * FROM users_1 UNION ALL SELECT * FROM users_2 UNION ALL SELECT * FROM users_3 UNION ALL SELECT * FROM users_4 UNION ALL SELECT * FROM users_5 UNION ALL SELECT * FROM users_6 UNION ALL SELECT * FROM users_7 UNION ALL SELECT * FROM users_8 UNION ALL SELECT * FROM users_9 UNION ALL SELECT * FROM users_a UNION ALL SELECT * FROM users_b UNION ALL SELECT * FROM users_c UNION ALL SELECT * FROM users_d UNION ALL SELECT * FROM users_e UNION ALL SELECT * FROM users_f EOT; return $this->setTable(DB::raw("({$sql}) AS users_all")); } }
除了上面的方法,將合並查詢寫在 PHP 代碼里,也可以寫到 SQL 里。具體的做法是新增一個視圖,視圖的定義就是 UNION ALL 合並查詢的 SQL 語句,仍舊以上面的 users 表為例子。
CREATE VIEW users_all AS SELECT * FROM users_0 UNION ALL SELECT * FROM users_1 UNION ALL SELECT * FROM users_2 UNION ALL SELECT * FROM users_3 UNION ALL SELECT * FROM users_4 UNION ALL SELECT * FROM users_5 UNION ALL SELECT * FROM users_6 UNION ALL SELECT * FROM users_7 UNION ALL SELECT * FROM users_8 UNION ALL SELECT * FROM users_9 UNION ALL SELECT * FROM users_a UNION ALL SELECT * FROM users_b UNION ALL SELECT * FROM users_c UNION ALL SELECT * FROM users_d UNION ALL SELECT * FROM users_e UNION ALL SELECT * FROM users_f;
視圖可以看作虛擬的表,在 Laravel 中創建對應的 Model 類(如:UserAll.php),在統計查詢時直接使用新建的 UserAll 類來進行操作就行了。
總結:原理都是使用 UNION ALL 合並查詢結果集,具體是寫在 PHP 代碼里還是寫在 SQL 里,就看個人選擇了。