主頁 > 資料庫 > 分庫分表之第五篇

分庫分表之第五篇

2020-09-20 13:16:50 資料庫

分庫分表之第五篇

    • 9.案例
      • 9.1.需求描述
      • 9.2.資料庫設計
      • 9.3.環境說明
      • 9.4.環境準備
        • 9.4.1.mysql主從同步(windows)
        • 9.4.2.初始化資料庫
      • 9.5.實作步驟
        • 9.5.1搭建maven工程
        • 9.5.2 分片配置
        • 9.5.3 添加商品
        • 9.5.4 查詢商品
        • 9.5.5 統計商品
      • 10. 總結

 

9.案例

9.1.需求描述

電商平臺商品串列展示,每個串列項中除了包含商品基本資訊、商品描述資訊之外,還包括了商品所屬的店鋪資訊,如下 :
在這里插入圖片描述
本案例實作功能如下:
1、添加商品
2、商品分頁查詢
3、商品統計

9.2.資料庫設計

資料庫設計如下,其中商品與店鋪資訊之間進行了垂直分庫,分為了PRODUCT_DB(商品庫)和STORE_DB(店鋪庫);商品資訊還進行了垂直分表,分為了商品基本資訊(product_info)和商品描述資訊(product_descript),地理區域資訊(region)作為公共表,冗余在兩庫中 :
在這里插入圖片描述
考慮到商品資訊的資料增長性,對PRODUCT_DB(商品庫)進行了水平分庫,分片鍵使用店鋪id,分片策略為店鋪 ID%2 + 1,因此商品描述資訊對所屬店鋪ID進行了冗余;
對商品基本資訊(product_info)和商品描述資訊(product_descript)進行水平分表,分片鍵使用商品id,分片策略為 商品ID%2 + 1,并將為這兩個表設定為系結表,避免笛卡爾積join;
為避免主鍵沖突,ID生成策略采用雪花演算法來生成全域唯一ID,最終資料庫設計為下圖:
在這里插入圖片描述
要求使用讀寫分離來提升性能,可用性,

9.3.環境說明

  • 作業系統 :win10
  • 資料庫 :MySQL-5.7.25
  • JDK :64位 jdk1.8.0_201
  • 應用框架 :spring-bbot-2.1.3.RELEASE,MyBatis3.5.0
  • Sharding-JDBC :sharding-jdbc-spring-boot-starter-4.0.0-RC1

9.4.環境準備

9.4.1.mysql主從同步(windows)

參考讀寫分離章節,對以下庫進行主從同步配置 :

 # 設定需要同步的資料庫 
 binlog‐do‐db=store_db 
 binlog‐do‐db=product_db_1 
 binlog‐do‐db=product_db_2

9.4.2.初始化資料庫

創建store_db資料庫,并執行以下腳本創建表 :

DROP TABLE IF EXISTS `region`; CREATE TABLE `region` (
`id` bigint(20) NOT NULL COMMENT 'id',
`region_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地理區域編碼',
`region_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地理區域名稱',
`level` tinyint(1) NULL DEFAULT NULL COMMENT '地理區域級別(省、市、縣)',
`parent_region_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '上級地理區域編碼',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `region` VALUES (1, '110000', '北京', 0, NULL); INSERT INTO `region` VALUES (2, '410000', '河南省', 0, NULL); INSERT INTO `region` VALUES (3, '110100', '北京市', 1, '110000'); INSERT INTO `region` VALUES (4, '410100', '鄭州市', 1, '410000');
DROP TABLE IF EXISTS `store_info`; CREATE TABLE `store_info` (
`id` bigint(20) NOT NULL COMMENT 'id',
`store_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '店鋪名稱',
`reputation` int(11) NULL DEFAULT NULL COMMENT '信譽等級',
`region_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '店鋪所在地',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `store_info` VALUES (1, 'XX零食店', 4, '110100'); INSERT INTO `store_info` VALUES (2, 'XX飲品店', 3, '410100');

創建product_db_1、product_db_2資料庫,并分別對兩庫執行以下腳本創建表:

DROP TABLE IF EXISTS `product_descript_1`; CREATE TABLE `product_descript_1` (
`id` bigint(20) NOT NULL COMMENT 'id',
`product_info_id` bigint(20) NULL DEFAULT NULL COMMENT '所屬商品id',
`descript` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '商品描述',`store_info_id` bigint(20) NULL DEFAULT NULL COMMENT '所屬店鋪id', PRIMARY KEY (`id`) USING BTREE,
INDEX `FK_Reference_2`(`product_info_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
DROP TABLE IF EXISTS `product_descript_2`; CREATE TABLE `product_descript_2` (
`id` bigint(20) NOT NULL COMMENT 'id',
`product_info_id` bigint(20) NULL DEFAULT NULL COMMENT '所屬商品id',
`descript` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '商品描述', `store_info_id` bigint(20) NULL DEFAULT NULL COMMENT '所屬店鋪id',
PRIMARY KEY (`id`) USING BTREE,
INDEX `FK_Reference_2`(`product_info_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
DROP TABLE IF EXISTS `product_info_1`; CREATE TABLE `product_info_1` (
`product_info_id` bigint(20) NOT NULL COMMENT 'id',
`store_info_id` bigint(20) NULL DEFAULT NULL COMMENT '所屬店鋪id',
`product_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
COMMENT '商品名稱',
`spec` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '規
格',
`region_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT
'產地',
`price` decimal(10, 0) NULL DEFAULT NULL COMMENT '商品價格',
`image_url` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT
'商品圖片',
PRIMARY KEY (`product_info_id`) USING BTREE,
INDEX `FK_Reference_1`(`store_info_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
DROP TABLE IF EXISTS `product_info_2`; CREATE TABLE `product_info_2` (
`product_info_id` bigint(20) NOT NULL COMMENT 'id',
`store_info_id` bigint(20) NULL DEFAULT NULL COMMENT '所屬店鋪id',
`product_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
COMMENT '商品名稱',
`spec` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '規
格',
`region_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT
'產地',
`price` decimal(10, 0) NULL DEFAULT NULL COMMENT '商品價格',
`image_url` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT
'商品圖片',
PRIMARY KEY (`product_info_id`) USING BTREE,
INDEX `FK_Reference_1`(`store_info_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; DROP TABLE IF EXISTS `region`;
CREATE TABLE `region` (
`id` bigint(20) NOT NULL COMMENT 'id', `region_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地理區域編碼',
`region_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地理區域名稱',
`level` tinyint(1) NULL DEFAULT NULL COMMENT '地理區域級別(省、市、縣)',
`parent_region_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '上級地理區域編碼',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `region` VALUES (1, '110000', '北京', 0, NULL); INSERT INTO `region` VALUES (2, '410000', '河南省', 0, NULL); INSERT INTO `region` VALUES (3, '110100', '北京市', 1, '110000'); INSERT INTO `region` VALUES (4, '410100', '鄭州市', 1, '410000');

9.5.實作步驟

9.5.1搭建maven工程

(1)搭建工程maven工程shopping,并做好Spring boot相關配置,
(2)引入maven依賴

<dependency>
<groupId>org.apache.shardingsphere</groupId> 
<artifactId>sharding‐jdbc‐spring‐boot‐starter</artifactId> 
<version>4.0.0‐RC1</version>
</dependency>

9.5.2 分片配置

既然是分庫分表,那么就需要定義多個真實資料源,每一個資料庫鏈接資訊就是一個資料源定義,如 :

spring.shardingsphere.datasource.m0.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m0.driver‐class‐name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m0.url = jdbc:mysql://localhost:3306/store_db?useUnicode=true
spring.shardingsphere.datasource.m0.username = root
spring.shardingsphere.datasource.m0.password = root

m0,就是這個真實資料源的名稱,然后需要告訴Sharding-JDBC,咋們有那些真實資料源,如 :

spring.shardingsphere.datasource.names = m0,m1,m2,s0,s1,s2

如果需要配置讀寫分離,還需要告訴Sharding-JDBC,這么多真實資料源,那么有幾個是一套讀寫分離?也就是定義主從邏輯資料源 :

spring.shardingsphere.sharding.master‐slave‐rules.ds0.master‐data‐source‐name=m0 
spring.shardingsphere.sharding.master‐slave‐rules.ds0.slave‐data‐source‐names=s0

若我們已經對m0和s0做了mysql主從同步,那我們需要告訴Sharding-JDBC,m0、s0為一組主從同步資料源,其 中m0為主,s0為從,并且定義名稱為ds0,這個ds0就是主從邏輯資料源,
最終配置如下,具體的分庫分表策略參考注釋內容:

# 真實資料源定義 m為主庫 s為從庫 spring.shardingsphere.datasource.names = m0,m1,m2,s0,s1,s2
spring.shardingsphere.datasource.m0.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m0.driver‐class‐name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m0.url = jdbc:mysql://localhost:3306/store_db?useUnicode=true
spring.shardingsphere.datasource.m0.username = root
spring.shardingsphere.datasource.m0.password = root
spring.shardingsphere.datasource.m1.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver‐class‐name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m1.url = jdbc:mysql://localhost:3306/product_db_1? useUnicode=true
spring.shardingsphere.datasource.m1.username = root
spring.shardingsphere.datasource.m1.password = root
spring.shardingsphere.datasource.m2.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver‐class‐name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m2.url = jdbc:mysql://localhost:3306/product_db_2? useUnicode=true
spring.shardingsphere.datasource.m2.username = root
spring.shardingsphere.datasource.m2.password = root
spring.shardingsphere.datasource.s0.type = com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.s0.driver‐class‐name = com.mysql.jdbc.Driver spring.shardingsphere.datasource.s0.url = jdbc:mysql://localhost:3307/store_db?useUnicode=true spring.shardingsphere.datasource.s0.username = root spring.shardingsphere.datasource.s0.password = root
spring.shardingsphere.datasource.s1.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.s1.driver‐class‐name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.s1.url = jdbc:mysql://localhost:3307/product_db_1? useUnicode=true
spring.shardingsphere.datasource.s1.username = root
spring.shardingsphere.datasource.s1.password = root
spring.shardingsphere.datasource.s2.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.s2.driver‐class‐name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.s2.url = jdbc:mysql://localhost:3307/product_db_2? useUnicode=true
spring.shardingsphere.datasource.s2.username = root
spring.shardingsphere.datasource.s2.password = root
# 主庫從庫邏輯資料源定義 ds0為store_db ds1為product_db_1 ds2為product_db_2
spring.shardingsphere.sharding.master‐slave‐rules.ds0.master‐data‐source‐name=m0 
spring.shardingsphere.sharding.master‐slave‐rules.ds0.slave‐data‐source‐names=s0
spring.shardingsphere.sharding.master‐slave‐rules.ds1.master‐data‐source‐name=m1 spring.shardingsphere.sharding.master‐slave‐rules.ds1.slave‐data‐source‐names=s1
spring.shardingsphere.sharding.master‐slave‐rules.ds2.master‐data‐source‐name=m2 spring.shardingsphere.sharding.master‐slave‐rules.ds2.slave‐data‐source‐names=s2
# 默認分庫策略,以store_info_id為分片鍵,分片策略為store_info_id % 2 + 1,也就是store_info_id為雙數的 資料進入ds1,為單數的進入ds2
spring.shardingsphere.sharding.default‐database‐strategy.inline.sharding‐column = store_info_id spring.shardingsphere.sharding.default‐database‐strategy.inline.algorithm‐expression = ds$‐> {store_info_id % 2 + 1}
# store_info分表策略,固定分配至ds0的store_info真實表
spring.shardingsphere.sharding.tables.store_info.actual‐data‐nodes = ds$‐>{0}.store_info
spring.shardingsphere.sharding.tables.store_info.table‐strategy.inline.sharding‐column = id
spring.shardingsphere.sharding.tables.store_info.table‐strategy.inline.algorithm‐expression = store_info
# product_info分表策略,分布在ds1,ds2的product_info_1 product_info_2表 ,分片策略為product_info_id % 2 + 1,product_info_id生成為雪花演算法,為雙數的資料進入product_info_1表,為單數的進入product_info_2 表
spring.shardingsphere.sharding.tables.product_info.actual‐data‐nodes = ds$‐> {1..2}.product_info_$‐>{1..2}
spring.shardingsphere.sharding.tables.product_info.table‐strategy.inline.sharding‐column = product_info_id
spring.shardingsphere.sharding.tables.product_info.table‐strategy.inline.algorithm‐expression = product_info_$‐>{product_info_id % 2 + 1} 
spring.shardingsphere.sharding.tables.product_info.key‐generator.column=product_info_id
spring.shardingsphere.sharding.tables.product_info.key‐generator.type=SNOWFLAKE
# product_descript分表策略,分布在ds1,ds2的product_descript_1 product_descript_2表 ,分片策略為 product_info_id % 2 + 1,id生成為雪花演算法,product_info_id為雙數的資料進入product_descript_1表,為單 數的進入product_descript_2
spring.shardingsphere.sharding.tables.product_descript.actual‐data‐nodes = ds$‐> {1..2}.product_descript_$‐>{1..2}
spring.shardingsphere.sharding.tables.product_descript.table‐strategy.inline.sharding‐column = product_info_id
spring.shardingsphere.sharding.tables.product_descript.table‐strategy.inline.algorithm‐ expression = product_descript_$‐>{product_info_id % 2 + 1} 
spring.shardingsphere.sharding.tables.product_descript.key‐generator.column=id
spring.shardingsphere.sharding.tables.product_descript.key‐generator.type=SNOWFLAKE
# 設定product_info,product_descript為系結表
spring.shardingsphere.sharding.binding‐tables[0] = product_info,product_descript
# 設定region為廣播表(公共表),每次更新操作會發送至所有資料源 
spring.shardingsphere.sharding.broadcast‐tables=region
# 打開sql輸出日志 spring.shardingsphere.props.sql.show = true

9.5.3 添加商品

物體類 :
在這里插入圖片描述
DAO實作

@Mapper
   @Component
   public interface ProductDao {
//添加商品基本資訊
@Insert("insert into product_info(store_info_id,product_name,spec,region_code,price)
value(#{storeInfoId},#{productName},#{spec},#{regionCode},#{price})") @Options(useGeneratedKeys = true,keyProperty = "productInfoId",keyColumn = "id") 
int insertProductInfo(ProductInfo productInfo);
//添加商品描述資訊
@Insert("insert into product_descript(product_info_id,descript,store_info_id) value(#
{productInfoId},#{descript},#{storeInfoId})")
@Options(useGeneratedKeys = true,keyProperty = "id",keyColumn = "id") 
int insertProductDescript(ProductDescript productDescript);
}

service實作,針對垂直分庫的兩個庫,分別實作店鋪服務、商品服務

@Service
   public class ProductServiceImpl implements ProductService {
       @Autowired
       private ProductDao productDao;
       @Override
       @Transactional
       public void createProduct(ProductInfo product) {
ProductDescript productDescript = new ProductDescript(); productDescript.setDescript(product.getDescript()); productDao.insertProductInfo(product);//新增商品基本資訊 productDescript.setProductInfoId(product.getProductInfoId());
productDescript.setStoreInfoId(product.getStoreInfoId()); //冗余店鋪資訊
productDao.insertProductDescript(productDescript);//新增商品描述資訊 
}
}

controller實作:

/**
* 賣家商品展示 */
   @RestController
   public class SellerController {
       @Autowired
       private ProductService productService;
		@PostMapping("/products")
		public String createProject(@RequestBody ProductInfo productInfo) {
		productService.createProduct(productInfo);
		return "創建成功!"; 
	}

單元測驗:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ShardingJdbcDemoBootstrap.class) public class ShardingTest {
       @Autowired
       ProductService productService;
       @Test
       public void testCreateProduct(){
		for(long i=1;i<10;i++){ //store_info_id,product_name,spec,region_code,price,image_url ProductInfo productInfo = new ProductInfo(); productInfo.setProductName("Java編程思想"+i); productInfo.setDescript("Java編程思想是一本非常好的Java教程"+i); productInfo.setRegionCode("110000"); productInfo.setStoreInfoId(1);
		productInfo.setPrice(new BigDecimal(i)); productService.createProduct(productInfo);
		} 
}

這是使用了sharding-jdbc所提供的全域主鍵生成方式之一雪花演算法,來生成全域業務唯一主鍵,通過添加商品介面新增商品進行分庫驗證,store_info_id為偶數的資料在product_db_1,為奇數的資料在product_db_2,
通過添加商品介面新增商品進行分表驗證,product_id為偶數的資料在product_info_1、product_descript_1,為奇數的資料在product_info_2、produt_descript_2,

9.5.4 查詢商品

Dao實作 :
在ProductDao中定義商品查詢方法 :

@Select("select i.*, d.descript, r.region_name placeOfOrigin " +
"from product_info i join product_descript d on i.id = d.product_info_id " +
"join region r on r.region_code = i.region_code order by i.id desc limit #{start},#
{pageSize}")
List<ProductInfo> selectProductList(@Param("start")int start,@Param("pageSize") int pageSize);

Service實作 :
在ProductServiceImpl定義商品查詢方法 :

 @Override
   public List<ProductInfo> queryProduct(int page,int pageSize) {
	int start = (page‐1)*pageSize;
	return productDao.selectProductList(start,pageSize); 
}

Controller實作 :

@GetMapping(value = "/products/{page}/{pageSize}")
public List<ProductInfo> queryProduct(@PathVariable("page")int page,@PathVariable("pageSize")int pageSize){
	return productService.queryProduct(page,pageSize); 
}

單元測驗 :

@Test
public void testSelectProductList(){
	List<ProductInfo> productInfos = productService.queryProduct(1,10);
	System.out.println(productInfos); 
}

通過查詢商品串列介面,能夠查詢到所有分片的商品資訊,關聯的地理區域,店鋪資訊正確,
總結 :
分頁查詢是業務中最常見的場景,Sharding-jdbc支持常用關系資料庫的分頁查詢,不過Sharding-jdbc的分頁功能比較容易讓使用者誤解,用戶通常認為分頁歸并會占用大量記憶體,在分布式的場景中,將LIMIT 10000000,10改寫為Limit 0,10000000,才能保證其資料的正確性,用戶非常容易產生ShardingSphere會將大量無意義的資料加載至記憶體中,造成記憶體溢位風險的錯覺,其實大部分情況都通過流式歸并獲取資料結果集,因此Sharding-Sphere會通過結果集的next方法將無需取出的資料全部跳過,并不會將其存入記憶體,
但同時需要注意的是,由于排序的需要,大量的資料仍然需要傳輸到Sharding-JDBC的記憶體空間,因此,采用LIMIT這種方式分頁,并非最佳實踐,由于LIMIT并不能通過索引查詢資料,因此如果可以保證ID的連續性,通過ID進行分頁是比較好的解決方案,例如 :

SELECT * FROM t_order WHERE id > 100000 AND id <= 100010 ORDER BY id;

或通過記錄上次查詢結果的最后一條記錄的ID進行下一頁的查詢,例如 :

SELECT * FROM t_order WHERE id > 10000000 LIMIT 10;

排序功能是由Sharding-jdbc的排序歸并來完成,由于在SQL中存在ORDER BY陳述句,因此每個資料結果集自身是有序的,因此只需要將資料結果集當前游標指向的資料值進行排序即可,這相當于多個有序的陣列進行排序,歸并排序是最適合此場景的排序演算法,

9.5.5 統計商品

本小節實作商品總數統計,商品分組統計
Dao實作,在ProductDao中定義 :

//總數統計
@Select("select count(1) from product_info") 
int selectCount();
//分組統計
@Select("select count(1) as num from product_info group by region_code having num>1 ORDER BY region_code ASC")
List<Map> selectProductGroupList();

單元測驗 :

	@Test
   public void testSelectCount(){
		int i = productDao.selectCount(); 
		System.out.println(i);
   }
   @Test
   public void testSelectGroupList(){
	List<Map> maps = productDao.selectProductGroupList();
	System.out.println(maps);
}

總結 :
分組統計
分組統計也是業務中常見的場景,分組功能的實作由Sharding-jdbc分組歸并完成,分組歸并的情況最為復雜,它分為流式分組歸并和記憶體分組歸并,流式分組歸并要求SQL的排序項與分組項的欄位必須保存一致,否則只能通過記憶體歸并才能保證其資料的正確性,
舉例說明,假設根據科目分片,表結構中包含考生的姓名(為了簡單起見,不考慮重名的情況)和分數,通過SQL獲取每位考生的總分,可通過如下SQL :

SELECT name, SUM(score) FROM t_score GROUP BY name ORDER BY name;

在分組項與排序項完全一致的情況下,取得的資料是連續的,分組所需的資料全數存在于各個資料結果集的當前游標所指向的資料值,因此可以采用流式歸并,如下圖所示,
在這里插入圖片描述
進行歸并時,邏輯與排序歸并類似, 下圖展現了進行next呼叫的時候,流式分組歸并是如何進行的,
在這里插入圖片描述
通過圖中我們可以看到,當進行第一次next呼叫時,排在佇列首位的t_score_java將會被彈出佇列,并且將分組值 同為“Jetty”的其他結果集中的資料一同彈出佇列, 在獲取了所有的姓名為“Jetty”的同學的分數之后,進行累加操 作,那么,在第一次next呼叫結束后,取出的結果集是“Jetty”的分數總和, 與此同時,所有的資料結果集中的游標 都將下移至資料值“Jetty”的下一個不同的資料值,并且根據資料結果集當前游標指向的值進行重排序, 因此,包含 名字順著第二位的“John”的相關資料結果集則排在的佇列的前列,

10. 總結

為什么分庫分表?分庫分表就是為了解決由于資料量過大而導致資料庫性能降低的問題,將原來獨立的資料庫拆分成若干資料庫組成 ,將資料大表拆分成若干資料表組成,使得單一資料庫、單一資料表的資料量變小,從而達到提升資料庫性能的目的,
分庫分表方式:垂直分表、垂直分庫、水平分庫、水平分表
分庫分表帶來問題:由于資料分散在多個資料庫,服務器導致了事務一致性問題、跨節點join問題、跨節點分頁、 排序、函式,主鍵需要全域唯一,公共表,
Sharding-JDBC基礎概念:邏輯表,真實表,資料節點,系結表,廣播表,分片鍵,分片演算法,分片策略,主鍵生 成策略
Sharding-JDBC核心功能:資料分片,讀寫分離
Sharding-JDBC執行流程: SQL決議 => 查詢優化 => SQL路由 => SQL改寫 => SQL執行 => 結果歸并
最佳實踐:
系統在設計之初就應該對業務資料的耦合松緊進行考量,從而進行垂直分庫、垂直分表,使資料層架構清晰明了,
若非必要,無需進行水平切分,應先從快取技術著手降低對資料庫的訪問壓力,如果快取使用過后,資料庫訪問量 還是非常大,可以考慮資料庫讀、寫分離原則,若當前資料庫壓力依然大,且業務資料持續增長無法估量,最后可 考慮水平分庫、分表,單表拆分資料控制在1000萬以內,
附 SQL支持說明
詳細參考:https://shardingsphere.apache.org/document/current/cn/features/sharding/use-norms/sql/ 說明:以下為官方顯示內容,具體是否適用以實際測驗為準 ,
支持的SQL

SQL必要條件
SELECT * FROM tbl_name  
SELECT * FROM tbl_name WHERE (col1 = ? or col2 = ?) and col3 = ?  
   
SELECT * FROM tbl_name WHERE col1 = ? ORDER BY col2 DESC LIMIT ?  
SELECT COUNT(*), SUM(col1), MIN(col1), MAX(col1), AVG(col1) FROM tbl_name WHERE col1 =?  
SELECT COUNT(col1) FROM tbl_name WHERE col2 = ? GROUP BY col1 ORDER BY col3 DESC LIMIT ?, ?  
INSERT INTO tbl_name (col1, col2,…) VALUES (?, ?, …)  
INSERT INTO tbl_name VALUES (?, ?,…)  
INSERT INTO tbl_name (col1, col2, …) VALUES (?, ?, …), (?, ?, …)  
UPDATE tbl_name SET col1 = ? WHERE col2 = ?  
DELETE FROM tbl_name WHERE col1 = ?  
CREATE TABLE tbl_name (col1 int, …)  
ALTER TABLE tbl_name ADD col1 varchar(10)  
DROP TABLE tbl_name  
TRUNCATE TABLE tbl_name  
CREATE INDEX idx_name ON tbl_name  
DROP INDEX idx_name ON tbl_name  
DROP INDEX idx_name  
SELECT DISTINCT * FROM tbl_name WHERE col1 = ?  
SELECT COUNT(DISTINCT col1) FROM tbl_name  

不支持的SQL

SQL不支持原因
INSERT INTO tbl_name (col1, col2, …) VALUES(1+2, ?, …) VALUES陳述句不支持運算 運算式
INSERT INTO tbl_name (col1, col2, …) SELECT col1, col2, … FROM tbl_name WHERE col3 = ? INSERT … SELECT
SELECT COUNT(col1) as count_alias FROM tbl_name GROUP BY col1 HAVING count_alias > ? HAVING
SELECT * FROM tbl_name1 UNION SELECT * FROM tbl_name2 UNION
SELECT * FROM tbl_name1 UNION ALL SELECT * FROM tbl_name2 UNION ALL
SELECT * FROM ds.tbl_name1 包含schema
SELECT SUM(DISTINCT col1), SUM(col1) FROM tbl_name 詳見DISTINCT支持情況詳 細說明

DISTINCT支持情況詳細說明
支持的SQL

SELECT DISTINCT * FROM tbl_name WHERE col1 = ?
SELECT DISTINCT col1 FROM tbl_name
SELECT DISTINCT col1, col2, col3 FROM tbl_name
SELECT DISTINCT col1 FROM tbl_name ORDER BY col1
SELECT DISTINCT col1 FROM tbl_name ORDER BY col2
SELECT DISTINCT(col1) FROM tbl_name
SELECT AVG(DISTINCT col1) FROM tbl_name
SELECT SUM(DISTINCT col1) FROM tbl_name
SELECT COUNT(DISTINCT col1) FROM tbl_name
SELECT COUNT(DISTINCT col1) FROM tbl_name GROUP BY col1 SELECT COUNT(DISTINCT col1 + col2) FROM tbl_name
SELECT COUNT(DISTINCT col1), SUM(DISTINCT col1) FROM tbl_name 
SELECT COUNT(DISTINCT col1), col1 FROM tbl_name GROUP BY col1 
SELECT col1, COUNT(DISTINCT col1) FROM tbl_name GROUP BY col1

不支持的SQL

SQL不支持原因
SELECT SUM(DISTINCT col1), SUM(col1) FROM tbl_name 同時使用普通聚合函式和DISTINCT聚合函式

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/89051.html

標籤:MySQL

上一篇:集群搭建

下一篇:php環境配置 wampserver 資料庫無法連接

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more