file-type

大数据量下数据库优化:分库分表策略详解

PDF文件

下载需积分: 0 | 598KB | 更新于2024-08-05 | 197 浏览量 | 2 下载量 举报 收藏
download 立即下载
在IT行业中,随着业务的不断增长,数据库优化成为至关重要的环节。当你遇到写入数据量急剧增加、单表数据量庞大、查询性能下降、磁盘空间压力增大以及高并发写入请求等问题时,数据库优化方案中的“分库分表”策略显得尤为重要。本篇文章将深入探讨在数据库优化过程中如何实施分库分表,以应对系统发展带来的挑战。 首先,当数据量达到千万甚至亿级别,传统的单表存储无法满足性能需求。即使使用索引,索引空间也会随着数据量增加而占用更多磁盘空间,这可能导致频繁的磁盘I/O,降低查询效率。提升查询性能的关键在于合理设计表结构和索引策略,可能需要采用分区或分片的方式,将数据分散到多个独立的物理存储区域,减少对单一索引的依赖。 其次,随着数据量的增大,数据库备份和恢复时间延长,影响系统的可用性和稳定性。为支持大数据量,可以考虑使用分布式存储和备份策略,比如分布式数据库或者实时的数据冗余,确保在主库故障时,备份库或从库能够快速接管服务,减少中断时间。 再者,为了实现不同模块数据的隔离,避免单点故障影响全局,分库分表需要按照业务逻辑进行数据划分,例如用户数据和用户关系数据分开存储在不同的数据库中。这样即使一个模块的数据库出现问题,其他模块仍能正常运行,提高系统的容错性和可靠性。 最后,针对数据库写入性能较弱的问题,特别是高并发写入场景,可以通过水平扩展来应对。通过增加数据库服务器的数量,将写入请求分散到多个服务器,每个服务器负责一部分数据的写入,从而降低单台服务器的压力。此外,还可以考虑使用更高效的数据库引擎、优化事务处理策略等手段,提高写入性能。 总结来说,分库分表是数据库优化的一种常见策略,旨在通过数据分布和资源调度,解决高并发、大数据量带来的性能和可用性问题。理解并熟练应用这一技术,有助于企业级应用在快速增长的业务环境中保持稳定和高效。在实际操作中,应根据具体业务场景灵活选择和调整分库分表的方法,以达到最佳的数据库优化效果。

相关推荐

filetype

#include "gd32f4xx_gpio.h" #include "gd32f4xx_rcu.h" #include "gd32f4xx_sdio.h" #include "gd32f4xx_misc.h" #include "Serial.h" #include "sdcard.h" #include "Delay.h" #include "ff.h" #include <string.h> #include <stdio.h> uint32_t SD_Get_RCA(void) { //发送 CMD3(请求分配 RCA) sdio_command_response_config(3, 0, SDIO_RESPONSETYPE_SHORT); // uint32_t timeout = 1000; // while (!sdio_flag_get(SDIO_FLAG_CMDRECV)) { // if (timeout-- == 0) { // return 0; // } // } sdio_flag_clear(SDIO_FLAG_CMDRECV); //从 RESP1 寄存器提取 RCA(高16位) uint32_t RCA = (sdio_response_get(SDIO_RESPONSE0) >> 16); return RCA; } void TF_Init() { uint32_t RCA=SD_Get_RCA(); rcu_periph_clock_enable(RCU_SDIO); rcu_periph_clock_enable(RCU_GPIOC); gpio_mode_set(GPIOC,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_PIN_9); gpio_output_options_set(GPIOC,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_9); sdio_clock_config(SDIO_SDIOCLKEDGE_RISING,SDIO_CLOCKBYPASS_DISABLE,SDIO_CLOCKPWRSAVE_DISABLE,256); sdio_bus_mode_set(SDIO_BUSMODE_4BIT); sdio_clock_enable(); sdio_power_state_set(SDIO_POWER_ON); Delay_ms(2); // sdio_wait_type_set(); sdio_command_response_config(0,0,SDIO_RESPONSETYPE_NO); //发送CMD0,复位卡 while(sdio_flag_get(SDIO_FLAG_CMDSEND)==SET); sdio_command_response_config(8,0x1AA,SDIO_RESPONSETYPE_SHORT); //发送CMD8,检查电压支持 uint32_t response = sdio_response_get(SDIO_RESP0); sdio_command_response_config(55,RCA<<16,SDIO_RESPONSETYPE_SHORT); //发送CMD55,下次命令时特定应用命令 sdio_command_response_config(41,(1UL << 30) | 0x00FF8000,SDIO_RESPONSETYPE_LONG); while((response&0x80000000)==0); sdio_csm_enable(); sdio_dsm_enable(); sdio_command_response_config(2,0,SDIO_RESPONSETYPE_LONG); sdio_command_response_config(7,RCA,SDIO_RESPONSETYPE_SHORT); //发送CMD7,选择卡 sdio_command_response_config(16,512,SDIO_RESPONSETYPE_SHORT); } void TF_WriteData(uint8_t *data,uint32_t Len,uint32_t timeout,uint32_t WritAddr) { uint32_t RCA=SD_Get_RCA(); sdio_command_response_config(24,WritAddr,SDIO_RESPONSETYPE_SHORT); //CMD24单块写,CMD25多块写 sdio_wait_type_set(SDIO_WAITTYPE_NO); while(sdio_flag_get(SDIO_FLAG_CMDRECV)); sdio_flag_clear(SDIO_FLAG_CMDRECV); sdio_data_config(timeout,Len,SDIO_DATABLOCKSIZE_512BYTES); sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK,SDIO_TRANSDIRECTION_TOCARD); sdio_dma_disable(); sdio_command_response_config(13,RCA<<16,SDIO_RESPONSETYPE_SHORT); for(uint16_t i=0;i<128;i++) { sdio_data_write(*(uint32_t*)data); data+=4; } while(sdio_flag_get(SDIO_FLAG_DTEND)); sdio_flag_clear(SDIO_FLAG_DTEND); nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); nvic_irq_enable(SDIO_IRQn,2,2); sdio_interrupt_enable(SDIO_INT_DTCRCERR); sdio_interrupt_enable(SDIO_INT_FLAG_DTEND); } uint32_t TF_ReadData(uint8_t *buffer,uint32_t timeout) { uint32_t RCA=SD_Get_RCA(); sdio_command_response_config(17,RCA,SDIO_RESPONSETYPE_SHORT); //发送CMD17,读取单个块 sdio_data_config(timeout,512,SDIO_DATABLOCKSIZE_512BYTES); sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK,SDIO_TRANSDIRECTION_TOSDIO); sdio_dma_disable(); //禁用DMA,使用轮询 while (sdio_flag_get(SDIO_FLAG_RXDTVAL)==SET) //等待数据可用 for(uint16_t i=0;i<128;i++) { buffer[i]=sdio_data_read(); } while (sdio_flag_get(SDIO_FLAG_DTEND)==SET) //等待数据可用 sdio_flag_clear(SDIO_FLAG_DTEND); return *buffer; } void SDIO_IRQHandler() { if(sdio_interrupt_flag_get(SDIO_INT_FLAG_DTCRCERR)==SET) { sdio_command_response_config(12,0,SDIO_RESPONSETYPE_SHORT); } sdio_interrupt_flag_clear(SDIO_INT_FLAG_DTCRCERR); if(sdio_interrupt_flag_get(SDIO_INT_FLAG_DTEND)==SET) { TF_Init(); } sdio_interrupt_flag_clear(SDIO_INT_FLAG_DTEND); } #define CONFIG_FILE "config.ini" #define FLASH_RATIO_ADDR 0x0000 // 变比存储地址 #define FLASH_LIMIT_ADDR 0x0004 // 阈值存储地址 FATFS fs; // FatFs文件系统对象 FIL fil; // 文件对象 FRESULT fr; // 文件操作结果 // 解析配置文件 int parse_config(const char* buffer, float* ratio, float* limit) { if (buffer == NULL || ratio == NULL || limit == NULL) return 0; char *p = (char*)buffer; *ratio = 0.0f; *limit = 0.0f; int found = 0; // 查找Ratio部分 while ((p = strstr(p, "[Ratio]")) != NULL) { p += strlen("[Ratio]"); char *ch0 = strstr(p, "Ch0"); if (ch0 && sscanf(ch0, "Ch0 = %f", ratio) == 1) { found++; break; } } p = (char*)buffer; // 查找Limit部分 while ((p = strstr(p, "[Limit]")) != NULL) { p += strlen("[Limit]"); char *ch0 = strstr(p, "Ch0"); if (ch0 && sscanf(ch0, "Ch0 = %f", limit) == 1) { found++; break; } } return (found == 2); } sd_error_enum sd_init_status = SD_ERROR; // SD卡初始化状态 void update_config_from_sd(void) { FIL config_file; UINT bytes_read; char buffer[256]; float ratio = 0.0f, limit = 0.0f; // SD卡重新初始化 if(sd_init_status != SD_OK) { printf("Reinitializing SD card...\r\n"); sd_init_status = sd_init(); if(sd_init_status != SD_OK) { printf("SD init failed: %d\r\n", sd_init_status); return; } } // 挂载文件系统(带超时) FRESULT fr; uint32_t mount_timeout = 5000; do { fr = f_mount(0,&fs); // 挂载到根目录 if(fr == FR_OK) break; delay_1ms(1); } while(mount_timeout-- > 0); if(fr != FR_OK) { printf("Mount error: %d\r\n", fr); return; } printf("Filesystem mounted\r\n"); // 检查文件是否存在 - 使用绝对路径 FILINFO fno; fr = f_stat("config.ini", &fno); // 关键修复:添加根目录前缀 if(fr != FR_OK) { printf("config.ini not found! Error: %d\r\n", fr); f_mount(0, NULL); return; } // 打开文件 f_mkdir("/"); // 确保根目录存在 fr = f_open(&config_file, "config.ini", FA_READ); // 使用绝对路径 if(fr != FR_OK) { printf("File open error: %d\r\n", fr); f_mount(0, NULL); return; } // 读取文件内容 fr = f_read(&config_file, buffer, sizeof(buffer)-1, &bytes_read); if(fr != FR_OK || bytes_read == 0) { printf("Read error: %d, Bytes: %d\r\n", fr, bytes_read); f_close(&config_file); f_mount(0, NULL); return; } buffer[bytes_read] = '\0'; f_close(&config_file); printf("File content:\r\n%s\r\n", buffer); // 打印文件内容 // 解析配置 if(parse_config(buffer, &ratio, &limit)) { printf("Parsed: Ratio=%.2f, Limit=%.2f\r\n", ratio, limit); // 保存到FLASH spi_flash_sector_erase(FLASH_RATIO_ADDR); spi_flash_buffer_write((uint8_t*)&ratio, FLASH_RATIO_ADDR, sizeof(ratio)); spi_flash_sector_erase(FLASH_LIMIT_ADDR); spi_flash_buffer_write((uint8_t*)&limit, FLASH_LIMIT_ADDR, sizeof(limit)); } else { printf("Config parse failed\r\n"); } // 卸载文件系统 f_mount(0, NULL); printf("Config update complete\r\n"); } // 命令处理函数 void process_command(const char* cmd) { if (strcmp(cmd, "conf") == 0) { USART0_SendData((uint16_t*)"Updating config...\r\n", 20); update_config_from_sd(); } else if (strcmp(cmd, "help") == 0) { USART0_SendData((uint16_t*)"Available commands:\r\n", 21); USART0_SendData((uint16_t*)" conf - Update config from SD card\r\n", 36); USART0_SendData((uint16_t*)" help - Show this help\r\n", 25); } else { char unknown_msg[64]; sprintf(unknown_msg, "Unknown command: %s\r\n", cmd); USART0_SendData((uint16_t*)unknown_msg, strlen(unknown_msg)); USART0_SendData((uint16_t*)"Type 'help' for available commands\r\n", 36); } } FATFS fs; FIL current_log_file, current_sample_file, current_overlimit_file, current_hidedata_file; uint8_t log_file_open = 0, sample_file_open = 0, overlimit_file_open = 0, hidedata_file_open = 0; uint32_t log_id = 0; // 辅助函数:获取日期时间字符串 void get_datetime_string(char* datetime_str) { // 需要实现RTC获取时间功能 // 格式: YYYYMMDDHHMMSS sprintf(datetime_str, "20250101120000"); // 示例 } // 辅助函数:从Flash获取下一个日志ID uint32_t get_next_log_id(void) { uint32_t id = 0; // 从Flash读取ID (地址0x2000) // spi_flash_buffer_read((uint8_t*)&id, 0x2000, 4); return id; } // 辅助函数:保存日志ID到Flash void save_log_id_to_flash(uint32_t id) { // spi_flash_sector_erase(0x2000); // spi_flash_buffer_write((uint8_t*)&id, 0x2000, 4); } // 1. 存储系统初始化 void storage_init(void) { FRESULT res; // 挂载文件系统 res = f_mount(1,&fs); if (res != FR_OK) { USART0_SendData((uint16_t*)"SD mount failed\r\n", 16); return; } // 创建存储目录 f_mkdir("sample"); f_mkdir("overLimit"); f_mkdir("log"); f_mkdir("hideData"); // 初始化日志ID log_id = get_next_log_id(); // 创建日志文件 char log_filename[32]; sprintf(log_filename, "log/log%u.txt", log_id); res = f_open(¤t_log_file, log_filename, FA_CREATE_ALWAYS | FA_WRITE); if (res == FR_OK) { log_file_open = 1; // 更新日志ID并保存 save_log_id_to_flash(log_id + 1); } } void log_operation(const char* operation) { if (!log_file_open) return; char datetime_str[16]; get_datetime_string(datetime_str); char log_entry[128]; sprintf(log_entry, "[%s] %s\r\n", datetime_str, operation); UINT bytes_written; f_write(¤t_log_file, log_entry, strlen(log_entry), &bytes_written); f_sync(¤t_log_file); } void store_sample_data(float voltage) { if (!sample_file_open) { char datetime_str[16]; get_datetime_string(datetime_str); char filename[32]; sprintf(filename, "sample/sampleData%s.txt", datetime_str); if (f_open(¤t_sample_file, filename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) { sample_file_open = 1; } } if (sample_file_open) { char data_line[64]; sprintf(data_line, "%.1fV\r\n", voltage); UINT bytes_written; f_write(¤t_sample_file, data_line, strlen(data_line), &bytes_written); f_sync(¤t_sample_file); } } void store_overlimit_data(float voltage, float limit) { if (!overlimit_file_open) { char datetime_str[16]; get_datetime_string(datetime_str); char filename[32]; sprintf(filename, "overLimit/overLimit%s.txt", datetime_str); if (f_open(¤t_overlimit_file, filename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) { overlimit_file_open = 1; } } if (overlimit_file_open) { char data_line[64]; sprintf(data_line, "%.1fV > %.1fV\r\n", voltage, limit); UINT bytes_written; f_write(¤t_overlimit_file, data_line, strlen(data_line), &bytes_written); f_sync(¤t_overlimit_file); } } void store_hidedata(float voltage) { if (!hidedata_file_open) { char datetime_str[16]; get_datetime_string(datetime_str); char filename[32]; sprintf(filename, "hideData/hideData%s.txt", datetime_str); if (f_open(¤t_hidedata_file, filename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) { hidedata_file_open = 1; } } if (hidedata_file_open) { char data_line[64]; sprintf(data_line, "HIDE: %.1fV\r\n", voltage); UINT bytes_written; f_write(¤t_hidedata_file, data_line, strlen(data_line), &bytes_written); f_sync(¤t_hidedata_file); } } void save_config_to_file(float ratio, float limit) { FIL config_file; if (f_open(&config_file, "config.ini", FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) { return; } char config_data[128]; sprintf(config_data, "[Ratio]\r\n" "Ch0 = %.1f\r\n" "\r\n" "[Limit]\r\n" "Ch0 = %.1f\r\n", ratio, limit); UINT bytes_written; f_write(&config_file, config_data, strlen(config_data), &bytes_written); f_close(&config_file); } // 写入Flash的辅助函数 void write_config_to_flash(float ratio, float limit) { spi_flash_sector_erase(FLASH_RATIO_ADDR); spi_flash_buffer_write((uint8_t*)&ratio, FLASH_RATIO_ADDR, sizeof(ratio)); spi_flash_sector_erase(FLASH_LIMIT_ADDR); spi_flash_buffer_write((uint8_t*)&limit, FLASH_LIMIT_ADDR, sizeof(limit)); } // 读取配置文件 void read_config_file(void) { UINT bytes_read; char buffer[256]; // 读取缓冲区 float ratio = 0.0f, limit = 0.0f; // 挂载文件系统 fr = f_mount(1,&fs); if (fr != FR_OK) { // 错误处理 return; } // 打开配置文件 fr = f_open(&fil, CONFIG_FILE, FA_READ); if (fr == FR_OK) { // 读取文件内容 fr = f_read(&fil, buffer, sizeof(buffer) - 1, &bytes_read); if (fr == FR_OK) { buffer[bytes_read] = '\0'; // 确保字符串结束 // 解析配置 if (parse_config(buffer, &ratio, &limit)) { // 写入Flash write_config_to_flash(ratio, limit); } } f_close(&fil); // 关闭文件 } } typedef enum { FR_OK = 0, /* (0) Succeeded */ FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */ FR_INT_ERR, /* (2) Assertion failed */ FR_NOT_READY, /* (3) The physical drive cannot work */ FR_NO_FILE, /* (4) Could not find the file */ FR_NO_PATH, /* (5) Could not find the path */ FR_INVALID_NAME, /* (6) The path name format is invalid */ FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */ FR_EXIST, /* (8) Acces denied due to prohibited access */ FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ FR_NOT_ENABLED, /* (12) The volume has no work area */ FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */ FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ } FRESULT; ====system init==== conf Command received: conf Updating config from SD card... Filesystem mounted SD init success config.ini not found! Error: 3 > test Command received: test ====System selftest===== flash.......ok flash ID:0xC84013 TF card...........ok TF card memory: 30721024 KB RTC: Current time: 2025-05-01 : 08:32:47 ====system selftest==== TF卡在读卡器中识别到了相应的配置文件,优化代码,解决问题

独角兽邹教授
  • 粉丝: 39
上传资源 快速赚钱