Rails 및 PostgreSQL을 사용하여 JSON 처리를 가속화하는 4가지 방법

AppLand은 소스 오픈 프레임워크로 개발자가 이를 사용하여 단말기에서 단말기까지의 코드와 데이터 흐름을 기록하고 분석하며 최적화할 수 있다.이 프레임워크는 Ruby, Java, Python(테스트 버전)에 클라이언트 에이전트를 제공하여 실행 코드를 기록하고 AppMaps라는 JSON 파일을 생성하는 데 사용된다.사용자는 AppMap extension for VS Code을 사용하여 로컬에서 앱맵을 보고 분석할 수 있으며, 앱맵을 앱랜드 서버에 전송해 분석, 공유, 토론 등을 할 수 있다.

AppLand 서버는 대형 AppMap JSON 파일을 수신하고 처리하는 데 사용됩니다.저희 스택은 허브 레일스와 포스트 greSQL입니다.물론 강력한 JSONB 데이터 형식을 사용하여 JSON 데이터를 데이터베이스에 저장합니다.AppLand의 초기 개발 단계에서 AppMap 파일은 보통 몇 KB에서 몇 백 KB까지 다양하다.그러나 얼마 지나지 않아 앱랜드 사용자들은 단일 자바와 루비 리포즈를 포함한 매우 큰 프로그램을 녹화하기 시작했다. 코드가 100만 줄에 달한다.수백 개, 수천 개의 JSON 파일이 이 대형 환매 프로토콜에서 생성되고 App Land로 밀려나면서 서버가 긴장됨에 따라 우리는 깊이 파고들고 최적화해야 한다.이 글은 대형 JSON 파일을 처리하기 위해 확장된 구조를 설명하고자 합니다.
따라서 우여곡절 없이 Rails와 PostgreSQL로 JSON 처리를 가속화하는 네 가지 방법이 있다.

1. POST에서 Rails JSON 구문 분석 건너뛰기


AppLand 서버가 AppMap 데이터를 수신할 때, 우리는 가능한 한 빨리 PostgreSQL에 입력하기를 희망합니다.Rails가 application/json의 HTTP 요청을 받으면 요청 JSON을 루비 대상으로 해석하고 이 데이터를 params으로 컨트롤러에 전달합니다.우리는 단지 데이터를 PostgreSQL에 삽입하고 싶을 뿐이다. PostgreSQL은 JSON 자체를 해석할 수 있기 때문에 Rails가 어떠한 해석도 할 필요가 없다.따라서 multipart/mixed이 아닌 application/json의 컨텐츠 유형을 전송하여 Rails JSON 해석 동작을 비활성화합니다.이런 방식을 통해 우리는 응용층에서 실행하는 요청 처리량을 최소화할 것이다.JSON 데이터는 PostgreSQL에 효율적으로 로드되며, Rails 프레임워크가 제공하는 모든 장점을 희생할 필요가 없습니다.
다음은 저희 Go client code sending multipart/mixed 의 예입니다.

2. 알고리즘 디자인을 중시한다.


수백 KB의 데이터에 대해 대부분의 단순 알고리즘의 성능은 대체로 같다.그러나 데이터가 수십 MB, 심지어 더 커지면서 알고리즘 설계가 중요해졌다.우리는 우리의 AppMap 후처리 알고리즘이 O(n²) running time이라는 것을 발견했다.우리는 이 알고리즘을 O (n) 로 다시 쓸 수 있다.다음은 시간과 메모리와 데이터 크기의 관계도에서 차이가 납니다.

이러한 컴퓨터 과학 기초 지식, 특히 데이터가 갈수록 커질 때를 기억해라!더 빠른 코드를 작성해서 나쁜 알고리즘을 최적화하려는 시도는 무의미하다.이 알고리즘은 그 자체가 효율적이기 때문에 일반 루비에서 잘 표현된다.그것은 22초 안에 지난 3분 동안의 일을 완성했다.

3. 색인과 생성된 열을 사용하여 대형 JSON 객체에 대한 액세스 속도 향상


JSONB의 묘미는'무모드'JSON의 유연성과 SQL과 관계의 강대성 사이에서 선택할 필요가 없다는 데 있다.
앞에서 말한 바와 같이 AppMap 데이터는 컨트롤러가 데이터베이스에 직접 기록합니다.잠시 후, 우리는 이 데이터들을 조회하고 검색하기 쉽게 하기를 희망합니다.이러한 작업의 효율성을 높이는 데 도움이 되는 두 가지 PostgreSQL 기술이 있습니다.
우선, 우리는 때때로 AppMaps에 들어가서 특정한 필드에 따라 검색하기를 원한다. 예를 들어 '탭' 이나 'metadata.name' 이다.우리는 JSONB 데이터에 색인을 추가함으로써 효율을 높일 수 있다.
둘째, 어떤 상황에서 우리는 JSONB 데이터의 하위 집합을 검색해야 한다. 많은 메가바이트의 JSONB 데이터를 분석할 필요가 없고 몇 개의 필드만 추출할 수 있다.따라서 데이터를 로드할 때 일부 JSON 데이터를 같은 기록의 열에 복제(또는 반규범화)합니다.Generated columns은 비규범화된 데이터가 항상 최신형으로 유지되도록 신속하고 효율적으로 설계되었습니다.
이 기술에 대한 더 많은 세부 사항은 제 동료의 댓글을 보십시오.

4. SQL 함수를 사용하여 데이터베이스의 JSONB 처리


데이터베이스는 데이터를 저장하는 데 쓰일 뿐만 아니라 데이터도 잘 처리할 수 있다.JSONB의 경우 PostgreSQL은 데이터를 선택하기 전에 그것들을 사용하여 데이터를 필터하고 변환할 수 있는 함수와 연산자를 제공합니다.데이터베이스에 있는 데이터를 처리하면 모든 도구를 사용하여 최상의 효과를 얻을 수 있습니다: PostgreSQL은 데이터 처리에 사용되고, Ruby는 전면을 후단에 붙이는 데 사용됩니다.다음은 데이터베이스에서 수행한 데이터 작업의 예입니다.

  • 은 특정 패키지, 클래스 또는 함수를 포함하는 모든 AppMap을 찾습니다.
  • 은 여러 AppMap에 사용되는 모든 코드의 패키지 및 클래스 계층을 구성합니다.
  • 은 여러 AppMap에 걸쳐 패키지 및 클래스의 종속성 다이어그램을 구성합니다.
  • 데이터베이스에서 이러한 계산을 통해 우리는 저장에 매우 가까운 데이터를 효율적으로 조작할 수 있고 불필요한 데이터를 데이터베이스에서 응용 층으로 전송하지 않을 수 있다.
    이것이 바로 우리의 명단이다.나는 네가 이곳에서 쓸모 있는 물건을 찾을 수 있기를 바란다.자신의 JSON 최적화 공유가 있다면 댓글로 알려주세요.
    또한 본고에서 묘사한 대부분의 최적화는 우리의 장기적인 가이드와 친구 Rafał Rzepecki이 디자인하고 개발한 것이다.고마워, 라파!

    영예상


    보상으로 여기 몇 가지 팁이 있습니다!

    SQL 로그 메시지 크기 제한


    기본적으로 Rails 프레임워크는 모든 SQL 문을 기록합니다.응용 프로그램이 데이터베이스에 대형 JSON 파일을 삽입할 때, 콘솔에서 메가바이트의 SQL INSERT 기록을 보는 것은 도움이 되지 않는다.
    이 Sequel 확장자를 생성하여 로그 메시지를 차단했습니다.
    # frozen_string_literal: true
    
    # Sequel database extension to truncate too long log entries.
    #
    # SQL statements longer than +sql_log_maxlen+ will get ellipsized in the logs.
    module TruncatedLogging
      DEFAULT_SQL_LOG_MAXLEN = 2048
      private_constant :DEFAULT_SQL_LOG_MAXLEN
    
      attr_writer :sql_log_maxlen
    
      def sql_log_maxlen
        @sql_log_maxlen ||= DEFAULT_SQL_LOG_MAXLEN
      end
    
      def log_connection_yield(sql, conn, args = nil)
        sql = sql[0...(sql_log_maxlen - 3)] + '...' if sql.length > sql_log_maxlen
        super(sql, conn, args)
      end
    end
    
    Sequel::Database.register_extension(:truncated_logging, TruncatedLogging)
    

    Sequel을 사용하여 JSON 생성 시 ActiveSupport 건너뛰기:: JSON


    ActiveSupport: JSON detects dates and times은 regexp를 사용하고 날짜 값을 Ruby 객체로 처리합니다.이 기능을 사용하지 않으므로 다른 갱신 세트에서 사용할 수 없습니다.
    # config/application.rb
    ...
        config.sequel.after_connect = proc do
          Sequel::Model.db.extension :truncated_logging
          Sequel.extension :core_to_json
        end
    ...
    
    # frozen_string_literal: true
    # lib/sequel/extensions/core_to_json.rb
    
    # ActiveSupport adds some pure ruby manipulation to #to_json
    # which isn't useful here and hurt performance. Use JSON.generate
    # directly to bypass it.
    def Sequel.object_to_json(obj, *args, &block)
      JSON.generate obj, *args, &block
    end
    

    좋은 웹페이지 즐겨찾기