SQL 聚合函数为什么比 Python 和 Java 慢(或穷人的 OLAP)?

40 阅读2分钟

一位用户在 Stack Overflow 上发帖询问为什么 SQL 聚合函数速度远低于 Python 和 Java。他使用 Postgres 8.3 在 Macbook Pro 上执行查询,查询时间为 200 毫秒,而 Java 和 Python 在执行相同的计算时只需要不到 20 毫秒(350,000 行)。

huake_00015_.jpg

解决方案

针对这个问题,有几位专家提出了不同的解决方案:

  1. 有专家指出,用户的测试方案并不合理。SQL 数据库需要执行多个步骤才能完成查询,而 Python 和 Java 则无需进行这些步骤。因此,这种比较并不公平。专家建议用户使用更合理的方式进行测试,例如比较 SQL 查询执行时间和 Python 读取数据并进行聚合计算的时间。

  2. 有专家建议用户尝试使用物化视图来提高查询速度。物化视图是预先计算并存储的结果集,可以大大减少查询时间。但是,物化视图也有其缺点,例如可能导致数据不一致。

  3. 有专家建议用户尝试将数据表设置为内存表。内存表将数据存储在内存中,可以大大提高查询速度。但是,内存表也有其缺点,例如可能会消耗大量内存。

  4. 有专家建议用户尝试使用 NoSQL 数据库。NoSQL 数据库通常比 SQL 数据库更快,但 NoSQL 数据库不适合所有场景。

  5. 有专家建议用户尝试使用其他 SQL 数据库。不同的 SQL 数据库性能可能不同,用户可以尝试使用性能更好的 SQL 数据库。

代码例子

以下是用户在 Stack Overflow 上提供的 Python 和 Java 代码示例:

import csv
import numpy as np

with open('350,000 responses.csv', 'r') as f:
    reader = csv.reader(f)
    data = list(reader)

a = np.array([row[1] for row in data], dtype=int)
b = np.array([row[2] for row in data], dtype=int)
c = np.array([row[3] for row in data], dtype=int)
d = np.array([row[4] for row in data], dtype=int)

print(np.mean(a))
print(np.mean(b))
print(np.mean(c))
print(np.mean(d))
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.Stream;

public class JavaOlap {

    public static void main(String[] args) throws IOException {
        // Read data from CSV file
        Stream<String> lines = Files.lines(Paths.get("350,000 responses.csv"));
        String[] data = lines.toArray(String[]::new);

        // Convert data to arrays of integers
        int[] a = new int[data.length];
        int[] b = new int[data.length];
        int[] c = new int[data.length];
        int[] d = new int[data.length];
        for (int i = 0; i < data.length; i++) {
            String[] row = data[i].split(",");
            a[i] = Integer.parseInt(row[1]);
            b[i] = Integer.parseInt(row[2]);
            c[i] = Integer.parseInt(row[3]);
            d[i] = Integer.parseInt(row[4]);
        }

        // Calculate averages
        double avgA = Arrays.stream(a).average().getAsDouble();
        double avgB = Arrays.stream(b).average().getAsDouble();
        double avgC = Arrays.stream(c).average().getAsDouble();
        double avgD = Arrays.stream(d).average().getAsDouble();

        // Print averages
        System.out.println(avgA);
        System.out.println(avgB);
        System.out.println(avgC);
        System.out.println(avgD);
    }
}

这些代码示例可以帮助读者更好地理解如何使用 Python 和 Java 进行数据聚合计算。