Очень низкая производительность в R для цикла или конкатенации - PullRequest
0 голосов
/ 11 июля 2019

Я написал фрагмент кода на R, который по сути соединяется с базой данных управления Монго, которая содержит список других баз данных.Затем он зацикливается на соединении с каждой базой данных, извлекает результаты из каждой базы данных (для моего примера это около 1 миллиона строк на базу данных из 35 баз данных) и создает большой фрейм со всеми результатами, который я затемИспользовать анализ преформ.

Примечание: Я делаю это специально для R, потому что хочу использовать это в качестве источника данных в Power BI.Запланированное обновление Power BI работает только для сценариев R, а не для python, и мне нужно сделать это в сценарии, потому что он мне нужен для динамического подключения и извлечения данных из ряда баз данных.

Проблема в том, что он работает, однако для извлечения и манипулирования данными из одной базы данных требуется более 15 минут, эти швы далеко-далеко, поскольку, по сути, все, что я здесь делаю, это извлечение данных из базы данных, добавление дополнительныхстолбец в результат и объединение результатов вместе.

Когда я извлекаю данные и не выполняю никаких манипуляций с данными, это занимает гораздо меньше времени

library(mongolite)

connectDB = function(database) {
  username = "user"
  password = "password"
  host = "host:port"
  # Using plain-text
  uri = sprintf("mongodb://%s:%s@%s/%s?authSource=admin", username, password, host, database)
  return(uri)
}

prepareData = function( object, selector, date = FALSE ) {
  if( !hasName(object, selector) ) {
    return( NA )
  }
  if( is.null( object[[selector]] ) ) {
    return( NA )
  }
  if( date ) {
    return ( as.character( object[[selector]] ) )
  }
  return( object[[selector]] )
}

databases = function() {
  table <- mongo( "databases", url = connectDB( 'management' ) )

  results <- table$iterate('{}', field = '{}')

  ids <- c()
  databaseNames <- c()

  while(!is.null(database <- databases$one())){
    ids <- c(ids, database$'_id')
    databaseNames <- c(databaseNames, database$'database'$'name')
  }
  databases = data.frame(
    ID = ids,
    DatabaseName = databaseNames
  )
  return(databases)
}

getUsers = function(databases) {
  # creating containers for each column in the table
  ids <- c()
  databaseIDs <- c()
  names <- c()
  createdAts <- c()
  updatedAts <- c()

  for (i in 1:nrow(databases)) {

    id = as.character(databases[i, 'ID'])
    databaseName = as.character(databases[i, 'DatabaseName'])

    users <- mongo('users', url = connectDB(databaseName))

    print(Sys.time())

    usersResults <- users$iterate('{}', field = '{}')

    while(!is.null(usersResult <- usersResults$one())){

      # selects data from user table

      ids <- c(ids, usersResult$'_id')

      databaseIDs <- c(databaseIDs, id)

      names <- c(names, prepareData( usersResult, 'name') )
      createdAts <- c(createdAts, prepareData( usersResult, 'created_at', TRUE) )
      updatedAts <- c(updatedAts, prepareData( usersResult, 'updated_at', TRUE) )
    }
    print(Sys.time())
    break
  }

  return (
    data.frame(
      #produce a table which pulls in the containers
      ID = ids,
      DatabaseID = databaseIDs,
      Name = names,
      CreatedAt = createdAts,
      UpdatedAt = updatedAts
    )
  )  
}

#run the script
users <- getUsers( databases())

Примечание: Сценарий также был анонимизирован, мой фактический вариант использования не для пользователей, это всего лишь пример, но я стремлюсь добиться того же результата

Примечание: Я также новичок в программировании на R, мой опыт работы в веб-разработке, особенно в JavaScript, NodeJS и PHP.То, как R строит фреймы, очень чуждо мне, так как оно сшивает противоположный путь, вместо того, чтобы строить ряд, вы строите столбец, так что это также может быть недостатком понимания

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...