Почему Spark долго вытаскивает данные из базы

Я использую hadoop со spark sql. Обычно когда я вытаскиваю 1000 колон, то это занимает 1-2 сек, но когда больше 2 тыс,то spark зависает и подгружает данные через мин


spark-submit --deploy-mode client --master yarn --num-executors=40 --executor-cores=2 --executor-memory=5G  /home/hdoop/SparkApplication/demo-0.0.1-SNAPSHOT.jar 

@Configuration
@EnableAutoConfiguration(exclude = {org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration.class})
public class SparkConfig {

    @Value("Test Spark Application")
    private String appName;
    @Value("local[*]")
    private String masterUri;

    @Bean
    public SparkConf sparkConf() {
        return new SparkConf()
                .setAppName(appName)
                .setMaster(masterUri)
                .set("spark.sql.debug.maxToStringFields", "1000")
                .setJars(new String[]
                {"/home/hdoop/SparkApplication/demo-0.0.1-SNAPSHOT.jar"
                ,"/home/hdoop/SparkApplication/spark-core_2.12-3.0.1.jar"
                ,"/home/hdoop/SparkApplication/postgresql-42.2.10.jar"});
    }

@Service
@EnableAutoConfiguration(exclude = {org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration.class})
public class StackOverFlow implements Serializable {

    @Autowired
    private SparkConf sparkConf;

    public List<Order> getObject(String param, String value, Long limit) {
        Encoder<Order> orderEncoder = Encoders.bean(Order.class);

        SparkSession session = SparkSession
                .builder()
                .config(sparkConf)
                .getOrCreate();

        if (!session.sqlContext().isTraceEnabled()) {
            SparkSession.setActiveSession(session);
        }
                                                                        
        Dataset<Row> jdbcDF = session.read()
                .format("jdbc")
                .option("url", "jdbc:postgresql:postgres:5432//orders")
                .option("driver", "org.postgresql.Driver")
                .option("query", "select * from orders o where " + param + " = '" + value + "' limit " + limit)
                .option("user", "root")
                .option("password", "password")
                .load();

        List<Order> orders = jdbcDF.as(orderEncoder).collectAsList();
        session.stop();
        return orders;
    }


Ответы (1 шт):

Автор решения: Alex Ott

Тут надо смотреть с обоих сторон:

  1. Какой план генерируется со стороны PostgreSQL - используются ли индексы, и т.п. для данных запросов.
  2. Спарк читает данные из БД в один поток, даже если имеется несколько экзекуторов. Существуют техники для паралеллизации чтения, такие как указание нескольких queries, или параметров типа numPartitions, etc. (документация) Например, вот ответы на эту тему: 1, 2
  3. Некоторые драйвера имеют не особо хорошие начальные параметры, так что можно посмотреть в сторону тюнинга fetchsize и прочих параметров описанных в документации. Например, если fetchsize по умолчанию 50, то для выборки 1000 строк нужно будет сделать 20 чтений, а если его увеличить до 1000, то это произойдет за раз.
→ Ссылка