当前位置:   article > 正文

数据开发工程师-面试题_数据工程师面试题

数据工程师面试题

1、数据仓库的结构?

数据仓库是一个用于存储、管理和分析大规模数据的集中式数据存储系统。它的结构通常包括以下主要组件和层次。

  • 数据源:数据仓库的数据源包括各种不同的数据系统,如关系数据库、日志文件、外部API、云存储等。数据从这些源头采集、抽取、转换和加载到数据仓库种。
  • 数据抽取:在这个阶段,数据从各个数据源中提取出来,以备后续处理。抽取的数据可能包括原始数据、历史数据、事务数据等。
  • 数据转换:在数据仓库中,数据通常需要经过清洗、转换和整合,以满足分析和报告需求。数据转换的任务包括数据清洗、字段映射、数据合并、计算指标等。
  • 数据加载:转换后的数据被加载到数据仓库中的不同层次,通常包括原始数据存储、中间数据存储和数据仓库数据存储。数据加载过程可以是批处理或实时流处理。
  • 数据存储层次:数据仓库包括多个存储层次,其中包括①原始数据存储,保留未经处理的原始数据,以备不同的分析需求;②数据仓库存储,包含已经经过清洗、转换和整合的数据,用于执行高级分析和报告。③数据汇总存储:包含已经汇总和预计算的数据,用于提高查询性能和执行复杂的分析任务。
  • 元数据管理:数据仓库需要维护元数据,以描述存储在其中的数据的结构、来源、定义、变换规则等信息。元数据对于数据仓库的管理和查询优化非常重要。
  • 数据访问层:数据仓库提供不同的方式供用户和应用程序访问数据,包括SQL查询、OLAP(在线分析处理)工具、报告工具和API等。
  • 查询和分析工具:数据仓库通常于各种查询和分析工具集成,以支持用户进行数据探索、查询和报告。
  • 安全性和权限控制:数据仓库需要实施严格的安全行和权限控制,以确保只有经过授权的用户可以访问和操作数据。
  • 监控和性能优化:数据仓库需要实时监控,以确保性能和可用性。性能优化是一个持续的过程,包括索引、分区、缓存等技术。

2、python-逆序对取模

逆序对取模通常需要使用归并排序算法。逆序对在一个数组中,如果一个数比其后面的数大,则称这两个数构成一个逆序对。

  1. def merge_sort(arr, mod):
  2. if len(arr) > 1:
  3. mid = len(arr) // 2
  4. left_half = arr[:mid]
  5. right_half = arr[mid:]
  6. left_half, left_inv_count = merge_sort(left_half, mod)
  7. right_half, right_inv_count = merge_sort(right_half, mod)
  8. merged_arr, split_inv_count = merge(left_half, right_half, mod)
  9. inv_count = left_inv_count + right_inv_count + split_inv_count
  10. return merged_arr, inv_count
  11. else:
  12. return arr, 0
  13. def merge(left, right, mod):
  14. merged_arr = []
  15. inv_count = 0
  16. i = j = 0
  17. while i < len(left) and j < len(right):
  18. if left[i] <= right[j]:
  19. merged_arr.append(left[i])
  20. i += 1
  21. else:
  22. merged_arr.append(right[j])
  23. j += 1
  24. inv_count += len(left) - i
  25. merged_arr.extend(left[i:])
  26. merged_arr.extend(right[j:])
  27. return merged_arr, inv_count
  28. def count_inverse_pairs(arr, mod):
  29. _, inv_count = merge_sort(arr, mod)
  30. return inv_count % mod
  31. # 示例用法
  32. arr = [2, 4, 1, 3, 5]
  33. mod = 1000000007
  34. result = count_inverse_pairs(arr, mod)
  35. print("逆序对数取模结果:", result)

3、Python-合并两个已排序的数组

方法:使用双指针的方法,遍历两个输入数组,逐个比较元素,将较小的元素添加到新数组中。

  1. def merge_sorted_arrays(arr1, arr2):
  2. merged_arr = []
  3. i = j = 0
  4. while i < len(arr1) and j < len(arr2):
  5. if arr1[i] < arr2[j]:
  6. merged_arr.append(arr1[i])
  7. i += 1
  8. else:
  9. merged_arr.append(arr2[j])
  10. j += 1
  11. # 将剩余的元素添加到新数组中
  12. while i < len(arr1):
  13. merged_arr.append(arr1[i])
  14. i += 1
  15. while j < len(arr2):
  16. merged_arr.append(arr2[j])
  17. j += 1
  18. return merged_arr
  19. # 示例用法
  20. arr1 = [1, 3, 5, 7]
  21. arr2 = [2, 4, 6, 8]
  22. result = merge_sorted_arrays(arr1, arr2)
  23. print("合并后的已排序数组:", result)

4、Spark和Hadoop是大数据处理领域的两个重要框架,它们有一些异同点。

相同点:

  • 都为开源框架,可以免费使用和修改。
  • 两者都旨在处理大规模数据,采用分布式计算模型,能够在多台计算节点上并行执行任务。
  • 容错性:两者都具备容错性,能够处理节点故障,并保证任务的完成。
  • 支持多种数据源:两者都可以处理不同的数据源,包括结构化数据(如关系型数据)、半结构化数据(XML,JSON)和非结构化数据(文本、日志等)
  • 支持多种编程语言:包括Java、Python、Scala等,使开发者可以使用他们熟悉的语言进行大数据处理。

不同点:

  • 数据处理模型:①Hadoop使用MapReduce模型,这是一种批处理模型,适用于离线的数据处理。MapReduce任务通常需要将数据写入磁盘中间存储,因此对于迭代算法或实时处理来说效率较低。②spark使用基于内存的计算模型,可以更高效地进行迭代处理和实时处理,因为它可以将中间数据存储在内存中。
  • 性能:①Spark通常比Hadoop的Mapreduce更快,尤其在迭代算法(如机器学习)和实时数据处理方面。这是因为spark充分利用了内存计算,减少了磁盘IO。②Hadoop的MapReduce更适合一次性、批处理式的任务。
  • API和生态系统:①Spark提供了更多的高级API,包括支持SQL查询的Spark SQL、机器学习库MLib、图处理库GraphX等,使得开发更加方便。②Hadoop生态系统包括Hive(支持SQL查询、pig(数据流脚本语言)、HBase(NoSQL数据库)等,但需要更多的工具和库来实现类似的功能。
  • 复杂度:①Spark通常更容易使用,因为它提供了高级API和更友好的编程模型。②Hadoop的MapReduce需要更多的手工编码和配置。
  • 资源管理器:①Hadoop使用YARN(Yet Another Resource Negotiator)作为资源管理器,负责分配集群资源给不同的任务。②Spark自带了一个资源管理器,称为Cluster Manager,也可以与YARN和Mesos等外部资源管理器集成。

5、Java-二分查找

  1. public int search(int[] nums, int left, int right, int target) {
  2. while (left <= right){
  3. int mid = left + (right - left) / 2;
  4. if (nums[mid] == target){
  5. return mid;
  6. }else if (nums[mid]< target){
  7. return search(num, mid + 1, right, target);
  8. }else{
  9. return search(num, left, mid - 1, target);
  10. }
  11. }
  12. return -1;
  13. }

6、Java-双指针

递增数组,判断数组中是否存在两个数之和为target,思路为双指针,一个begin,一个end,每次移动一个指针

  1. public int[] twoSum(int[] numbers, int target) {
  2. int p1 = 0;
  3. int p2 = numbers.length - 1;
  4. while (p1 < p2){
  5. int sum = numbers[p1] + numbers[p2];
  6. if (sum == target){
  7. return new int[]{p1 + 1, p2 + 1};
  8. } else if (sum < target){
  9. p1++;
  10. } else {
  11. p2--;
  12. }
  13. }
  14. //无解
  15. return new int[]{-1, -1};
  16. }

7、Java-最长递增子序列LIS(动态规划)

 给一个整数数组nums,找到其中最长严格递增子序列的长度。最优时间复杂度为O(nlogn)

  1. public int lengthOfLIS(int[] nums) {
  2. int dp[] = new int[nums.length];
  3. dp[0] = 1;
  4. int maxSeqLen = 1;
  5. for (int i=1; i<nums.length; i++) {
  6. //初始化为1
  7. dp[i] = 1;
  8. for (int j = 0; j <= i; j++) {
  9. //对dp[i]进行更新,严格递增
  10. if (nums[i] > nums[j]){
  11. dp[i] = Math.max(dp[i], dp[j]+1);
  12. }
  13. }
  14. maxSeqLen = Math.max(maxSeqLen, dp[i]);
  15. }
  16. return maxSeqLen;
  17. }

8、逆序链表两数求和

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

  1. /**
  2. * Definition for singly-linked list.
  3. * public class ListNode {
  4. * int val;
  5. * ListNode next;
  6. * ListNode(int x) { val = x; }
  7. * }
  8. */
  9. class Solution {
  10. public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
  11. ListNode pre = new ListNode(0);
  12. ListNode cur = pre;
  13. int carry = 0;
  14. while(l1 != null || l2 != null) {
  15. int x = l1 == null ? 0 : l1.val;
  16. int y = l2 == null ? 0 : l2.val;
  17. int sum = x + y + carry;
  18. carry = sum / 10;
  19. sum = sum % 10;
  20. cur.next = new ListNode(sum);
  21. cur = cur.next;
  22. if(l1 != null)
  23. l1 = l1.next;
  24. if(l2 != null)
  25. l2 = l2.next;
  26. }
  27. if(carry == 1) {
  28. cur.next = new ListNode(carry);
  29. }
  30. return pre.next;
  31. }
  32. }

9、Mysql的三范式

  • 第一范式(1NF):数据表中的每一列都包含不可再分的原子数据,也就是每个单元格中只能存储一个值。所有的数据必须是原子的,不能包含集合、数组、嵌套表格等非原子数据。

  • 第二范式(2NF):数据表必须符合第一范式(1NF)。所有非主键列(非关键字列)都必须完全依赖于候选键(主键)。 这意味着没有部分依赖,即表中的每一列都应该与主键有关系,而不是只与主键的一部分有关。

  • 第三范式(3NF):数据表必须符合第二范式(2NF)。所有非主键列都不应该传递依赖于主键。换句话说,非主键列之间不应该存在传递依赖关系。如果一个非主键列依赖于另一个非主键列,而后者又依赖于主键,那么就存在传递依赖,这需要通过分解表来消除。非主键都和主键直接相关,不存在间接相关。

10、Mysql的InnoDB和MyIsam的区别

  • InnoDB支持事务,MyISAM不支持事务。
  • InnoDB支持外键
  • InnoDB是聚集索引,MyISAM是非聚集索引
  • InnoDB不支持具体的行数;InnoDB的最小锁的粒度是行锁,MyISAM的最小粒度是表锁。

11、MySQL的隔离级别

  • 未提交读:即未提交也读,事务中间也可以读,容易产生脏读、幻读、不可重复读。
  • 已提交读:只有在事务提交后才可以读,避免了脏读,但是无法避免不可重复读、幻读。
  • 可重复读:在事务提交的时候,不可以读和修改数据,避免了脏读和不可重复读。
  • 串行读:隔离级别最高,所有的事务都是串行化执行,避免了脏读、幻读和不可重复读。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/289359
推荐阅读
相关标签
  

闽ICP备14008679号