服务器雪崩的应对策略之----SQL优化

2024-06-24 11:52

本文主要是介绍服务器雪崩的应对策略之----SQL优化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

SQL语句的优化是数据库性能优化的重要方面,特别是在处理大规模数据或高频访问时。作为一个C++程序员,理解SQL优化不仅有助于编写高效的数据库操作代码,还能增强对系统性能瓶颈的整体把握。以下是详细的SQL语句优化技巧和策略:

SQL优化

      • 1. 选择合适的数据类型
      • 2. 使用索引
      • 3. 优化查询
      • 4. 范式化和反范式化
      • 5. 查询重写
      • 6. 使用缓存
      • 7. 优化数据库设计
      • 8. 分析和监控
      • 9. 调整配置
          • 1、内存分配
          • 2、连接池

1. 选择合适的数据类型

示例

  • 使用CHAR而不是VARCHAR
 -- 如果用户的状态是固定长度(如'active', 'inactive'),可以使用CHARCREATE TABLE users (id INT PRIMARY KEY,status CHAR(8));
  • 使用TINYINT代替INT
    -- 如果用户的年龄范围在0-255,可以使用TINYINT
    CREATE TABLE users 
    (id INT PRIMARY KEY,age TINYINT
    );
    

2. 使用索引

示例

  • 创建索引

    -- 为用户的年龄创建索引
    CREATE INDEX idx_users_age ON users(age);
    
  • 避免过多的索引

    -- 如果只需查询用户的年龄和名字,不需要对所有列都创建索引
    CREATE INDEX idx_users_age_name ON users(age, name);
    
  • 组合索引

    -- 为用户的年龄和注册日期创建组合索引
    CREATE INDEX idx_users_age_reg_date ON users(age, registration_date);
    

3. 优化查询

示例

  • 选择合适的查询

    -- 避免使用SELECT *
    SELECT name, age FROM users WHERE age > 30;
    
  • 使用子查询和联结

    -- 将子查询改写为JOIN
    SELECT u.name, o.order_date
    FROM users u
    JOIN orders o ON u.id = o.user_id
    WHERE u.age > 30;
    
  • WHERE条件优化

    -- 将最可能过滤大量数据的条件放在前面
    SELECT * FROM users WHERE age > 30 AND status = 'active';
    
  • 避免函数和操作符

    -- 避免对列进行函数操作
    SELECT * FROM users WHERE registration_date >= '2023-01-01';
    

4. 范式化和反范式化

示例

  • 范式化

    -- 第三范式设计:拆分表结构
    CREATE TABLE orders 
    (id INT PRIMARY KEY,user_id INT,product_id INT,order_date DATE,FOREIGN KEY (user_id) REFERENCES users(id)
    );
    
  • 反范式化

    -- 在高频读取的情况下,减少JOIN操作,反范式化
    CREATE TABLE order_details 
    (id INT PRIMARY KEY,user_name VARCHAR(255),product_name VARCHAR(255),order_date DATE
    );
    

5. 查询重写

示例

  • EXISTS vs IN

    -- 使用EXISTS而不是IN
    SELECT name FROM users WHERE EXISTS 
    (SELECT 1 FROM orders WHERE orders.user_id = users.id AND orders.total > 100
    );
    
  • JOIN优化

    -- 使用临时表优化大表JOIN
    CREATE TEMPORARY TABLE temp_orders AS
    SELECT * FROM orders WHERE order_date >= '2023-01-01';SELECT u.name, t.order_date FROM users u JOIN temp_orders t ON u.id = t.user_id;
    

6. 使用缓存

示例

  • 查询缓存

    -- MySQL查询缓存示例(假设MySQL版本支持)
    SET GLOBAL query_cache_size = 1048576; -- 1MB
    
  • 应用缓存

    // 在C++应用层使用Memcached缓存常用数据
    // 使用libmemcached库
    #include <libmemcached/memcached.h>memcached_st *memc;
    memcached_return rc;
    memcached_server_st *servers = NULL;
    char *key = "user_123";
    char *value;memc = memcached_create(NULL);
    servers = memcached_server_list_append(servers, "localhost", 11211, &rc);
    rc = memcached_server_push(memc, servers);
    memcached_server_list_free(servers);value = memcached_get(memc, key, strlen(key), NULL, NULL, &rc);
    

7. 优化数据库设计

示例

  • 分区

    -- 将大表按月份分区
    CREATE TABLE orders 
    (id INT PRIMARY KEY,user_id INT,order_date DATE
    )
    PARTITION BY RANGE (YEAR(order_date)) 
    (PARTITION p2023 VALUES LESS THAN (2024),PARTITION p2024 VALUES LESS THAN (2025)
    );
    
  • 分片

    -- 数据库分片:例如根据用户ID进行分片
    -- 分片1:存储用户ID 1-1000
    -- 分片2:存储用户ID 1001-2000
    

8. 分析和监控

示例

  • 使用EXPLAIN

    -- 使用EXPLAIN分析查询执行计划
    EXPLAIN SELECT name FROM users WHERE age > 30;
    
  • 监控系统性能

    -- 监控查询时间、锁等待、磁盘IO等指标
    SHOW STATUS LIKE 'Handler_read_rnd_next';
    SHOW ENGINE INNODB STATUS;
    

9. 调整配置

示例

1、内存分配

调整数据库管理系统(DBMS)的内存配置参数,可以显著提高数据库性能。以下是MySQL的示例:

  • 调整InnoDB缓冲池大小:InnoDB缓冲池用于缓存数据和索引,是MySQL最重要的内存分配参数。

    -- 查看当前缓冲池大小
    SHOW VARIABLES LIKE 'innodb_buffer_pool_size';-- 将缓冲池大小设置为1GB
    SET GLOBAL innodb_buffer_pool_size = 1024 * 1024 * 1024;
    
  • 调整查询缓存大小:查询缓存可以缓存常见查询的结果。

    -- 查看当前查询缓存大小
    SHOW VARIABLES LIKE 'query_cache_size';-- 将查询缓存大小设置为64MB
    SET GLOBAL query_cache_size = 64 * 1024 * 1024;-- 启用查询缓存
    SET GLOBAL query_cache_type = 1;
    
2、连接池

使用数据库连接池可以减少数据库连接的建立和关闭开销,提高应用程序的性能。以下是如何在C++应用中使用连接池的示例,使用MySQL Connector/C++库:

  • 使用MySQL Connector/C++库配置连接池
    // 在C++应用中使用连接池
    // 使用MySQL Connector/C++库
    #include <mysql_driver.h>
    #include <mysql_connection.h>
    #include <cppconn/driver.h>
    #include <cppconn/connection.h>
    #include <cppconn/statement.h>
    #include <cppconn/exception.h>
    #include <cppconn/resultset.h>
    #include <mutex>
    #include <queue>
    #include <memory>
    #include <condition_variable>class ConnectionPool 
    {
    public:static ConnectionPool& getInstance() {static ConnectionPool instance;return instance;}std::shared_ptr<sql::Connection> getConnection() {std::unique_lock<std::mutex> lock(mutex_);while (pool_.empty()) {condition_.wait(lock);}auto conn = pool_.front();pool_.pop();return conn;}void releaseConnection(std::shared_ptr<sql::Connection> conn) {std::unique_lock<std::mutex> lock(mutex_);pool_.push(conn);condition_.notify_one();}private:ConnectionPool() {for (int i = 0; i < pool_size_; ++i) {auto conn = driver_->connect(url_, user_, password_);pool_.push(std::shared_ptr<sql::Connection>(conn, [this](sql::Connection* conn) {releaseConnection(std::shared_ptr<sql::Connection>(conn));}));}}~ConnectionPool() {while (!pool_.empty()) {pool_.pop();}}ConnectionPool(const ConnectionPool&) = delete;ConnectionPool& operator=(const ConnectionPool&) = delete;sql::mysql::MySQL_Driver* driver_ = sql::mysql::get_mysql_driver_instance();std::queue<std::shared_ptr<sql::Connection>> pool_;std::mutex mutex_;std::condition_variable condition_;const std::string url_ = "tcp://127.0.0.1:3306";const std::string user_ = "user";const std::string password_ = "password";const int pool_size_ = 10;
    };// 使用连接池获取和释放连接
    int main() 
    {auto& pool = ConnectionPool::getInstance();auto conn = pool.getConnection();try {std::shared_ptr<sql::Statement> stmt(conn->createStatement());std::shared_ptr<sql::ResultSet> res(stmt->executeQuery("SELECT 'Hello, World!' AS _message"));while (res->next()) {std::cout << res->getString("_message") << std::endl;}} catch (sql::SQLException &e) {std::cerr << "SQLException: " << e.what() << std::endl;}// 连接会自动返回到连接池return 0;
    }
    

这个示例展示了如何创建一个简单的连接池类,并在C++应用中使用该连接池来管理和复用数据库连接。连接池的使用可以显著减少数据库连接的建立和销毁时间,从而提高应用程序的性能和响应速度。

通过这些示例,可以更直观地理解各项SQL优化策略的具体应用及其效果。

这篇关于服务器雪崩的应对策略之----SQL优化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1090074

相关文章

uniapp接入微信小程序原生代码配置方案(优化版)

uniapp项目需要把微信小程序原生语法的功能代码嵌套过来,无需把原生代码转换为uniapp,可以配置拷贝的方式集成过来 1、拷贝代码包到src目录 2、vue.config.js中配置原生代码包直接拷贝到编译目录中 3、pages.json中配置分包目录,原生入口组件的路径 4、manifest.json中配置分包,使用原生组件 5、需要把原生代码包里的页面修改成组件的方

2024.6.24 IDEA中文乱码问题(服务器 控制台 TOMcat)实测已解决

1.问题产生原因: 1.文件编码不一致:如果文件的编码方式与IDEA设置的编码方式不一致,就会产生乱码。确保文件和IDEA使用相同的编码,通常是UTF-8。2.IDEA设置问题:检查IDEA的全局编码设置和项目编码设置是否正确。3.终端或控制台编码问题:如果你在终端或控制台看到乱码,可能是终端的编码设置问题。确保终端使用的是支持你的文件的编码方式。 2.解决方案: 1.File -> S

mysql索引四(组合索引)

单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引;组合索引,即一个索引包含多个列。 因为有事,下面内容全部转自:https://www.cnblogs.com/farmer-cabbage/p/5793589.html 为了形象地对比单列索引和组合索引,为表添加多个字段:    CREATE TABLE mytable( ID INT NOT NULL, use

mysql索引三(全文索引)

前面分别介绍了mysql索引一(普通索引)、mysql索引二(唯一索引)。 本文学习mysql全文索引。 全文索引(也称全文检索)是目前搜索引擎使用的一种关键技术。它能够利用【分词技术】等多种算法智能分析出文本文字中关键词的频率和重要性,然后按照一定的算法规则智能地筛选出我们想要的搜索结果。 在MySql中,创建全文索引相对比较简单。例如:我们有一个文章表(article),其中有主键ID(

mysql索引二(唯一索引)

前文中介绍了MySQL中普通索引用法,和没有索引的区别。mysql索引一(普通索引) 下面学习一下唯一索引。 创建唯一索引的目的不是为了提高访问速度,而只是为了避免数据出现重复。唯一索引可以有多个但索引列的值必须唯一,索引列的值允许有空值。如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该使用关键字UNIQUE,把它定义为一个唯一索引。 添加数据库唯一索引的几种

mysql索引一(普通索引)

mysql的索引分为两大类,聚簇索引、非聚簇索引。聚簇索引是按照数据存放的物理位置为顺序的,而非聚簇索引则不同。聚簇索引能够提高多行检索的速度、非聚簇索引则对单行检索的速度很快。         在这两大类的索引类型下,还可以降索引分为4个小类型:         1,普通索引:最基本的索引,没有任何限制,是我们经常使用到的索引。         2,唯一索引:与普通索引

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

【服务器运维】MySQL数据存储至数据盘

查看磁盘及分区 [root@MySQL tmp]# fdisk -lDisk /dev/sda: 21.5 GB, 21474836480 bytes255 heads, 63 sectors/track, 2610 cylindersUnits = cylinders of 16065 * 512 = 8225280 bytesSector size (logical/physical)

【服务器运维】CentOS6 minimal 离线安装MySQL5.7

1.准备安装包(版本因人而异,所以下面的命令中版本省略,实际操作中用Tab自动补全就好了) cloog-ppl-0.15.7-1.2.el6.x86_64.rpmcpp-4.4.7-23.el6.x86_64.rpmgcc-4.4.7-23.el6.x86_64.rpmgcc-c++-4.4.7-23.el6.x86_64.rpmglibc-2.12-1.212.el6.x86_64.r

【服务器运维】CentOS7 minimal 离线安装 gcc perl vmware-tools

0. 本机在有网的情况下,下载CentOS镜像 https://www.centos.org/download/ 1. 取出rpm 有的情况可能不需要net-tools,但是如果出现跟ifconfig相关的错误,就把它安装上。另外如果不想升级内核版本的话,就找对应内核版本的rpm版本安装 perl-Time-Local-1.2300-2.el7.noarch.rpmperl-Tim