sql跨表查询的三种方案总结

目录
  • 前言
  • 方案一:连接多个库,同步执行查询
    • 优点
    • 缺点
    • 代码执行
  • 方案二:在主数据库增加冗余表,通过定时更新,造成同库联表查询
    • 优点
    • 缺点
    • 相似实现场景
  • 方案三:dbLink本地连接多个库,在本地进行数据分析
    • 优点
    • 缺点

前言

最近又个朋友问我,如何进行sql的跨库关联查询? 首先呢,我们知道mysql是不支持跨库连接的,但是老话说得好,只要思想不滑坡,思想总比困难多!

PS: 问题摆在这里了,还能不解决是怎么的?

经过一番思考我给他提出了三个方案,虽然都不尽善尽美,但各领风骚!

连接方案,以postgreSql库为例。

方案一:连接多个库,同步执行查询

具体思路为在代码中分别连接多个库,查到一个库中所需要的数据之后,通过关键字段,同步执行去其他的库中进行查询相关数据,然后进行需要的数据分析或更新!

优点

  • 可以进行实时查询;
  • 可对数据进行按需修改及逻辑范围内的修改返回值;
  • 一般采用此方案,查询数据会分页查询,或查询条件精确,从而量会比较小,对服务器压力小;
  • 服务器静态分析数据,效率高;

缺点

  • 不适合进行大批数据写入/查询,会造成数据库连接超时或获取的数据流过大导致服务器内存被大量占用;
  • 同步执行策略,查询数据库用时和运行时间成正比;

代码执行

一些简单的代码逻辑,不会有人看不懂吧~~~

postgreSql.js

//链接多个数据库,并暴露
const pg = require('pg');
const sqlConfig = {
  testOnePgSql: {
    user: "postgres",
    database: "admindb",
    password: "123",
    host: "192.168.1.111",//数据库ip地址(胡乱写的,写自己的库ip哈)
    port: 5432, // 扩展属性
    max: 20, // 连接池最大连接数
    idleTimeoutMillis: 3000
  },
  //超岛商户
  testTwoPgSql: {
    //测试数据库
    user: "postgres",
    database: "admindb",
    password: "123",
    host: "192.168.1.112",//数据库ip地址(胡乱写的,写自己的库ip哈)
    port: 5432, // 扩展属性
    max: 20, // 连接池最大连接数
    idleTimeoutMillis: 3000
  },
  //桃娘商户
  testThreePgSql: {
    //测试数据库
    user: "postgres",
    database: "admindb",
    password: "123",
    host: "192.168.1.113",//数据库ip地址(胡乱写的,写自己的库ip哈)
    port: 5432, // 扩展属性
    max: 20, // 连接池最大连接数
    idleTimeoutMillis: 3000
  },
};
const testOnePgSql = new pg.Pool(sqlConfig.banuPgSql);
const testTwoPgSql = new pg.Pool(sqlConfig.testTwoPgSql);
const testThreePgSql = new pg.Pool(sqlConfig.testThreePgSql);
module.exports = {
  testOnePgSql,
  testTwoPgSql,
  testThreePgSql
};

封装查询pgsql方法

postgreSqlClass.js

let sqlMap = require('./postgreSql');
module.exports = {
  /**
   *查询pgsql数据
   * @param sqlSelect 查询语句 string
   * @param tenancy 商户id string
   */
  select(sqlSelect, tenancy) {
    //按需连接
    let pool = sqlMap[tenancy];
    return new Promise((resolve, reject) => {
      pool.connect(async function (err, connection) {
        if (err) {
          // 结束会话
          connection.release();
          return reject(err);
        }
        let result = await pgQuery(sqlSelect, connection);
        // 结束会话
        connection.release();
        return resolve(result);
      });
    });
  }

};
/**
 * pgsql查询数据
 * @param sqlQuery 查询语句
 * @param connection pgSql连接后的connection
 * @returns {Promise<unknown>}
 */
async function pgQuery(sqlQuery, connection) {
  return new Promise((resolve, reject) => {
    connection.query(sqlQuery, (err, rows) => {
      if (err) return reject(err);
      return resolve(rows.rows || []);
    });
  });
}

现在进行业务模块

test.js

  "use strict";
//引入pg函数
let PGSQL = require("./postgreSqlClass");
exports.getUserList = async () => {

  let sqlOneSelect = `${第一个表查询语句}`;
  let userList = await PGSQL.select(sqlSelect, "testOnePgSql");
  //获取对应two表的数据
  //...逻辑

  let sqlTwoSelect = `${第一个表查询语句}`;
  let userListTwo = await PGSQL.select(sqlTwoSelect, "testTwoPgSql");
  let result = [];
  //组合你想要的数据
  //...逻辑

  return result;
};

方案二:在主数据库增加冗余表,通过定时更新,造成同库联表查询

比如A库为主数据库,B、C为其他的增项库,我们需要将三个库中的user表进行数据联表查询; 具体思路为:

  • 在A库存在user表,此时创建冗余表user_two、user_three表,并字段对应B、C库的user表字段;
  • 通过代码逻辑,进行定时任务,将B、C表,数据更新至A库user_two、user_three表;
  • 在需要数据分析/查询时,仅查询A库即可,但需要将A库的user、user_two、user_three表进行按需取用;

优点

  • 化跨表查询为同表查询,执行逻辑更为简单;
  • 可进行大数据分析和大数据查询;
  • 可以预处理数据,提高分析速率;

缺点

  • 定时更新,不具备及时性;
  • 需要对应表有最后更新时间字段,否则同步数据会比较多;
  • 增加冗余表,会造成主表空间占用率增加;
  • 定时更新,会导致某一时间点有大量数据写入/修改数据,可能会影响数据读取,因此,建议多节点部署(读写、只读);

相似实现场景

  • T+1时间的报表展示;
  • 局域网本地数据库信息上报至线上数据库;

方案三:dbLink本地连接多个库,在本地进行数据分析

(极度不建议)

具体思路:

  • dblink就是我们在创建表的时候连接到我们的远程库,然后我们本地新建的表数据就是映射远程的表的数据。
  • 当我们创建一个以FEDERATED为存储引擎的表时,服务器在数据库目录只创建一个表定义文件。文件由表的名字开始,并有一个frm扩展名。无其它文件被创建,因为实际的数据在一个远程数据库上。这不同于为本地表工作的存储引擎的方式。

执行步骤:

  • 1.如我现在本地要连接我的阿里云的sys_user表,所以我需要在本地建一个相同字段的表,我取名叫sys_user_copy,并连接到远程库,建好后,我本地sys_user_copy的表里面的数据是映射远程的表的数据

  • 2.所以我关联查询,可以直接关联我本地sys_user_copy表从而查出来。改了本地的数据,远程的表数据也会跟着变

**开启FEDERATED引擎,**show engines

如果这里是NO,需要在配置文件[mysqld]中加入一行:federated

改完重启服务,就变成yes了。

  • 4 建表时加上连接

CREATE TABLE (......)
ENGINE =FEDERATED CONNECTION='mysql://username:password@hostname:port/database/tablename'

优点

  • 不需要程序员介入,不需要开发
  • 快速形成结果,如果只想查询一些数据的话

缺点

  • 本地表结构必须与远程表完全一样
  • 不支持事务
  • 不支持表结构修改
  • 删除本地表,远程表不会删除
  • 远程服务器必须是一个MySQL服务器
  • 并不会在本地写入数据库数据,实质上是一个软连接,查询大量数据会导致本地内存爆满,因为是查询多个数据库的数据到本地内存,然后在内存中进行计算,此时时间复杂度为O(N^2),空间复杂度也为O(N^2);500条数据,对应本地时间复杂度为25W,时间复杂度为25W;

可用于:两库之间数据导入,不涉及计算,即A导入B,不进行查询A\B进行计算写入C;

到此这篇关于sql跨表查询的三种方案总结的文章就介绍到这了,更多相关sql跨表查询 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • MySQL跨表查询与跨表更新

    有点 SQL 基础的朋友肯定听过 「跨表查询」,那啥是跨表更新啊? 背景 项目新导入了一批人员数据,这些人的有的部门名称发生了变化,有的联系方式发生了变化,暂且称该表为 t_dept_members, 系统中有另外一张表 t_user_info 记录了人员信息.要求将 t_dept_members 中有变化的信息更新到 t_user 表中,这个需求就是「跨表更新」啦 憨B SQL 直接被秒杀 不带脑子出门的就写出了下面的 SQL 看到身后 DBA 小段总在修仙,想着让他帮润色一下

  • MySql实现跨表查询的方法详解

    复制代码 代码如下: SELECT c.id, c.order_id, c.title, c.content, c.create_time, o.last_pic FROM `orders` o , `case` c WHERE c.order_id = o.order_id ORDER BY c.id DESC LIMIT 15; 关于跨表提取字段的方法!利用order_id相同字段,提取case中的id,order_id,title,content,create_time:orders表中的

  • mysql 跨表查询、更新、删除示例

    下面来谈谈跨表插入,更新和删除 首先讨论的是跨表查询: insert into `table_A` select * from `table_B`;注意*代表全部插入. 接着又讨论关于跨表更新 复制代码 代码如下: update `table_A`, `table_B` set `table_A`.`name` = `table_B`.`name` where `table_A`.`id` = `table_B`.`id`;

  • sql跨表查询的三种方案总结

    目录 前言 方案一:连接多个库,同步执行查询 优点 缺点 代码执行 方案二:在主数据库增加冗余表,通过定时更新,造成同库联表查询 优点 缺点 相似实现场景 方案三:dbLink本地连接多个库,在本地进行数据分析 优点 缺点 前言 最近又个朋友问我,如何进行sql的跨库关联查询? 首先呢,我们知道mysql是不支持跨库连接的,但是老话说得好,只要思想不滑坡,思想总比困难多! PS: 问题摆在这里了,还能不解决是怎么的? 经过一番思考我给他提出了三个方案,虽然都不尽善尽美,但各领风骚! 连接方案,以

  • django之跨表查询及添加记录的示例代码

    创建表 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many); 一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many). 创建一对一的关系:OneToOne("要绑定关系的表名") 创建一对多的关系:ForeignKey("要绑定关系的表名") 创建多对多的关系:ManyToMany("要绑定关系的表名")  会自动

  • 浅谈Java实现分布式事务的三种方案

    一.问题描述 用户支付完成会将支付状态及订单状态保存在订单数据库中,由订单服务去维护订单数据库.由库存服务去维护库存数据库的信息.下图是系统结构图: 如何实现两个分布式服务(订单服务.库存服务)共同完成一件事即订单支付成功自动减库存,这里的关键是如何保证两个分布式服务的事务的一致性. 尝试解决上边的需求,在订单服务中远程调用减库存接口,伪代码如下: 订单支付结果通知方法{ ​ 更新支付表中支付状态为"成功". ​ 远程调用减库存接口减库存. } 上边的逻辑说明: 1.更新支付表状态为本

  • 详解解Django 多对多表关系的三种创建方式

    目录 1.方式一:自动创建 2.方式二:纯手动创建 3.方式三:半自动创建 1.方式一:自动创建 # django orm 自动帮我们创建第三张表,我的app名字是app01, 表名为:app01_book_authors # 这种方式可以让Django迅速的帮我们建一张关系表出来,好处是可以通过这张表进行跨表查询,坏处是一张虚拟表,拓展性差. # 书籍表 class Book(models.Model): name = models.CharField(max_length=32) autho

  • sqlServer实现分页查询的三种方式

    目录 一.offset /fetch next关键字 二.利用max(主键) 三.利用row_number关键字 总结 sqlServer的分页查询和mysql语句不一样,有三种实现方式.分别是:offset /fetch next.利用max(主键).利用row_number关键字 一.offset /fetch next关键字 2012版本及以上才有,SQL server公司升级后推出的新方法. 公式: -- 分页查询公式-offset /fetch next select * from 表

  • js实现跨域访问的三种方法

    javascript跨域访问是web开发者经常遇到的问题,什么是跨域,一个域上加载的脚本获取或操作另一个域上的文档属性,下面将列出三种实现javascript跨域方法: 1.基于iframe实现跨域 基于iframe实现的跨域要求两个域具有aa.xx.com,bb.xx.com这种特点,也就是两个页面必须属于一个基础域(例如都是xxx.com,或是xxx.com.cn),使用同一协议(例如都是 http)和同一端口(例如都是80),这样在两个页面中同时添加document.domain,就可以实

  • django框架基于queryset和双下划线的跨表查询操作详解

    本文实例讲述了django框架基于queryset和双下划线的跨表查询操作.分享给大家供大家参考,具体如下: 前面篇随笔写的是基于对象的跨表查询:对象.objects.filter(...)  对象.关联对象_set.all(...)  -->反向 基于对象的跨表查询例如: book_obj= Book.objects.filter(id=4).first() #注意多了个first print(book_obj) #go 这里得到的是一个models对象 print(book_obj.publ

  • django框架使用views.py的函数对表进行增删改查内容操作详解【models.py中表的创建、views.py中函数的使用,基于对象的跨表查询】

    本文实例讲述了django框架使用views.py函数对表进行增删改查内容操作.分享给大家供大家参考,具体如下: models之对于表的创建有以下几种: 一对一:ForeignKey("Author",unique=True),  OneToOneField("Author") 一对多:ForeignKey(to="Publish",to_field="id",on_delete.CASCADE) 多对多:ManyToMany

  • 浅谈PostgreSQL表分区的三种方式

    目录 一.简介 二.三种方式 2.1.Range范围分区 2.2.List列表分区 2.3.Hash哈希分区 三.总结 一.简介 表分区是解决一些因单表过大引用的性能问题的方式,比如某张表过大就会造成查询变慢,可能分区是一种解决方案.一般建议当单表大小超过内存就可以考虑表分区了.PostgreSQL的表分区有三种方式: Range:范围分区: List:列表分区: Hash:哈希分区. 本文通过示例讲解如何进行这三种方式的分区. 二.三种方式 为方便,我们通过Docker的方式启动一个Postg

随机推荐