(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-5LHNRP9'); GraphQL Ruby. Hvernig er frammistaðan? - The Codest
The Codest
  • Um okkur
  • Þjónusta
    • Hugbúnaðarþróun
      • Framhliðþróun
      • Bakendaþróun
    • Staff Augmentation
      • Framhliðaráþrófarar
      • Bakhliðaráþróunaraðilar
      • Gagnaverkfræðingar
      • Skýjaverkfræðingar
      • Gæðatryggingartæknimenn
      • Annað
    • Það er ráðgjafi
      • Endurskoðun og ráðgjöf
  • Iðnaðargreinar
    • Fjártæknifyrirtæki og bankastarfsemi
    • E-commerce
    • Adtech
    • Heilbrigðistækni
    • Framleiðsla
    • Flutningar
    • Bifreiða
    • Internet hlutanna
  • Gildi fyrir
    • CEO
    • CTO
    • Afhendingarstjóri
  • Teymið okkar
  • Case Studies
  • Vitið hvernig
    • Blogg
    • Fundir
    • Vefnámskeið
    • Auðlindir
Starfsferilmöguleikar Hafðu samband
  • Um okkur
  • Þjónusta
    • Hugbúnaðarþróun
      • Framhliðþróun
      • Bakendaþróun
    • Staff Augmentation
      • Framhliðaráþrófarar
      • Bakhliðaráþróunaraðilar
      • Gagnaverkfræðingar
      • Skýjaverkfræðingar
      • Gæðatryggingartæknimenn
      • Annað
    • Það er ráðgjafi
      • Endurskoðun og ráðgjöf
  • Gildi fyrir
    • CEO
    • CTO
    • Afhendingarstjóri
  • Teymið okkar
  • Case Studies
  • Vitið hvernig
    • Blogg
    • Fundir
    • Vefnámskeið
    • Auðlindir
Starfsferilmöguleikar Hafðu samband
Aftur ör Farðu aftur
2019-10-08
Hugbúnaðarþróun

GraphQL Ruby. Hvernig er frammistaðan?

The Codest

Tomasz Szkaradek

Þróunarskipulagsarkitekt

GraphQL, eins og hvaða tækni sem er, hefur sín vandamál; sum þeirra stafa beint af arkitektúrnum en önnur eru nákvæmlega þau sömu og í hvaða annarri forritun sem er. Lausnirnar eru hins vegar gjörólíkar.

Hér er tómt.

Til að kynna vandamálið skulum við gera ráð fyrir eftirfarandi forritunararkitektúr:

https://drive.google.com/file/d/1N4sWPJSls0S8FFHbpHCUVHBNBpEuSsyz/view

Og hér er samsvarandi fyrirspurn í GraphQL til að hlaða niður gögn. Við sækjum allar tenglar, ásamt höfundinum og tenglum hans sem bætast við kerfið,

{
  allLinks {
    id
    url
    description
    createdAt
    postedBy {
 id
 name
 links {
 id
 }
    }
  }
}

Eins og sýnt er hér að neðan sjáum við hið klassíska n + 1-vandamál með tengslum.

Link Load (0.4ms)  SELECT "links".* FROM "links" ORDER BY created_at DESC
  ↳ app/controllers/graphql_controller.rb:5:in `execute'
  Notendahleðsla (0,3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 40], ["LIMIT", 1]]
  ↳ app/controllers/graphql_controller.rb:5:in `execute'
  Link Load (0.3ms)  SELECT "links".* FROM "links" WHERE "links"."user_id" = ?  [["user_id", 40]]
  ↳ app/controllers/graphql_controller.rb:5:in `execute'
  Hleðsla notanda (0,1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 38], ["LIMIT", 1]]
  ↳ app/controllers/graphql_controller.rb:5:in `execute'
  Link Load (0.1ms)  SELECT "links".* FROM "links" WHERE "links"."user_id" = ?  [["user_id", 38]]
  ↳ app/controllers/graphql_controller.rb:5:in `execute'
  Hleðsla notanda (0,2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 36], ["LIMIT", 1]]
  ↳ app/controllers/graphql_controller.rb:5:in `execute'
  Link Load (0.1ms)  SELECT "links".* FROM "links" WHERE "links"."user_id" = ?  [["user_id", 36]]
  ↳ app/controllers/graphql_controller.rb:5:in `execute'
  Hleðsla notanda (0,1 ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 34], ["LIMIT", 1]]
  ↳ app/controllers/graphql_controller.rb:5:in `execute'
  Link Load (0.2ms)  SELECT "links".* FROM "links" WHERE "links"."user_id" = ?  [["user_id", 34]]
  ↳ app/controllers/graphql_controller.rb:5:in `execute'
  Hleðsla notanda (0,1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 32], ["LIMIT", 1]]

Í þessu tilfelli virkar það nákvæmlega eins og þetta stykki af kóði:
Tengja.alla.korta(&:notandi).korta(&:tenglar).

Það virðist sem við vitum lausnina á vandamálinu: Link.includes(user: :links).map(&:user).map(&:links), en mun það virka í raun? Skoðum það!

Til að staðfesta lagfæringu breytti ég GraphQL Fyrirspurn til að nota aðeins nokkur reiti og engin tengsl.

{
  allLinks {
    id
    url
    description
    createdAt
  }
}

Því miður sýnir niðurstaðan að þrátt fyrir skort á tenglum varðandi notandann og tengla hans bætum við þessum gögnum við gagnagrunnsfyrirspurnina. Því miður eru þau óþörf og með enn flóknari uppbyggingu reynast þau einfaldlega óhagkvæm.

Vinnsla af GraphqlController#execute sem */*
  Breytur: {"query"=>"{n  allLinks {n    idn    urln    descriptionn    createdAtn  }n}", "graphql"=>{"query"=>"{n  allLinks {n    idn    urln    descriptionn    createdAtn  }n}"}}
  Hleðsla tengla (0,3 ms)  SELECT "links".* FROM "links" ORDER BY created_at DESC
  ↳ app/controllers/graphql_controller.rb:5:in `execute'
  Notandi hleðst inn (0,3ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)  [["id", 40], ["id", 38], ["id", 36], ["id", 34], ["id", 32], ["id", 30], ["id", 28], ["id", 26], ["id", 24], ["id", 22], ["id", 20], ["id", 18], ["id", 16], ["id", 14], ["id", 12], ["id", 10], ["id", 8], ["id", 6], ["id", 4], ["id", 2]]
  ↳ app/controllers/graphql_controller.rb:5:in `execute'
  Tengill hleðsla (0,3 ms)  SELECT "links".* FROM "links" WHERE "links"."user_id" IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)  [["user_id", 2], ["user_id", 4], ["user_id", 6], ["user_id", 8], ["user_id", 10], ["user_id", 12], ["user_id", 14], ["user_id", 16], ["user_id", 18], ["user_id", 20], ["user_id", 22], ["user_id", 24], ["user_id", 26], ["user_id", 28], ["user_id", 30], ["user_id", 32], ["user_id", 34], ["user_id", 36], ["user_id", 38], ["user_id", 40]]
  ↳ app/controllers/graphql_controller.rb:5:in `execute'
Lokið 200 OK á 39ms (Skoðanir: 0.7ms | ActiveRecord: 0.9ms | Úthlutanir: 8730)

Í GraphQL, slík vandamál eru leyst á annan hátt, einfaldlega með því að hlaða gögnum í lotum, með þeirri forsendu að gögnin séu nauðsynleg þegar þau eru sett í fyrirspurnina. Þetta er svokallað letilegt hleðslufyrirkomulag. Eitt af vinsælustu bókasöfnunum er https://github.com/Shopify/graphql-batch/.

Því miður er uppsetningin ekki eins vandræðalaus og hún kann að virðast. Gagnalóðararnir eru fáanlegir hér: https://github.com/Shopify/graphql-batch/tree/master/examples, ég meina Upphleðsluforrit flokk ogFélagasamhlutlari flokkur. Skoðum að setja upp klassískt gem 'graphql-batch' bókasafn og bæta því síðan við skemað okkar, sem og hleðsluforritum:

# graphql-ruby/app/graphql/graphql_tutorial_schema.rb
class GraphqlTutorialSchema < GraphQL::Schema
  query Types::QueryType
  mutation Types::MutationType
  use GraphQL::Batch
  ...
end

Og tegundir okkar:

# graphql-ruby/app/graphql/types/link_type.rb
module Types
  class LinkType < BaseNode
    field :created_at, DateTimeType, null: false
    field :url, String, null: false
    field :description, String, null: false
    field :posted_by, UserType, null: false, method: :user
    field :votes, [Types::VoteType], null: false

 def user
 Loaders::RecordLoader.for(User).load(object.user_id)
    end
  end
end

# graphql-ruby/app/graphql/types/user_type.rb
module Types
  class UserType < BaseNode
    field :created_at, DateTimeType, null: false
    field :name, String, null: false
    field :email, String, null: false
    field :votes, [VoteType], null: false
    field :links, [LinkType], null: false

 def links
 Loaders::AssociationLoader.for(User, :links).load(object)
    end
  end
end

Sem afleiðing af notkun hleðslutólanna samræmum við gögnin og förum í tvær einfaldar SQL-fyrirspurnir til að sækja gögnin:

Hóf POST "/graphql" fyrir ::1 þann 2021-06-16 22:40:17 +0200
   (0.1ms)  SELECT sqlite_version(*)
Vinnsla af GraphqlController#execute sem */*
  Breytur: {"query"=>"{n  allLinks {n    idn    urln    descriptionn    createdAtn    postedBy {n idn namen links {n idn }n    }n  }n}", "graphql"=>{"query"=>"{n  allLinks {n    idn    urln    descriptionn    createdAtn    postedBy {n idn namen links {n idn }n    }n  }n}"}}
  Link Load (0.4ms)  SELECT "links".* FROM "links"
  ↳ app/controllers/graphql_controller.rb:5:in `execute'
  Hlaða notanda (0.9ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)  [["id", 2], ["id", 4], ["id", 6], ["id", 8], ["id", 10], ["id", 12], ["id", 14], ["id", 16], ["id", 18], ["id", 20], ["id", 22], ["id", 24], ["id", 26], ["id", 28], ["id", 30], ["id", 32], ["id", 34], ["id", 36], ["id", 38], ["id", 40]]
  ↳ app/graphql/loaders/record_loader.rb:12:in `perform'
  Link Load (0.5ms)  SELECT "links".* FROM "links" WHERE "links"."user_id" IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)  [["user_id", 2], ["user_id", 4], ["user_id", 6], ["user_id", 8], ["user_id", 10], ["user_id", 12], ["user_id", 14], ["user_id", 16], ["user_id", 18], ["user_id", 20], ["user_id", 22], ["user_id", 24], ["user_id", 26], ["user_id", 28], ["user_id", 30], ["user_id", 32], ["user_id", 34], ["user_id", 36], ["user_id", 38], ["user_id", 40]]
  ↳ app/graphql/loaders/association_loader.rb:46:in `preload_association'
Lokið 200 OK á 62ms (Views: 1.3ms | ActiveRecord: 1.8ms | Allocations: 39887)

Það eru einnig aðrar lausnir sem leysa þetta vandamál, svo sem:

https://github.com/exAspArk/batch-loader#basic-example

Flækjustig fyrirspurna

N + 1-fyrirspurnir eru ekki allt, í GraphQL Við getum frjálslega borið næstu eiginleika yfir. Sjálfgefið er gildi þeirra stillt á 1. Þetta getur stundum verið of mikið fyrir netþjóninn, sérstaklega í aðstæðum þar sem við getum frjálslega raðað gögnum í hólf. Hvernig eigum við að takast á við þetta? Við getum takmarkað flækjustig fyrirspurnarinnar, en til þess þurfum við einnig að tilgreina kostnað þeirra í eiginleikunum. Sjálfgefið er gildi þeirra stillt á 1. Við stillum þennan kostnað með því að nota flækjustig: eiginleiki, þar sem við getum slegið inn gögn: svið: tenglar, [Tengiltípa], null: falskur, flækjustig: 101. Ef takmörkun á að virka, þarftu enn að setja hámarksmörk í kerfið þitt:

class GraphqlTutorialSchema < GraphQL::Schema
  query Types::QueryType
  mutation Types::MutationType
  use GraphQL::Batch
  max_complexity 100
  ...
end

Eftirlit

GraphQL Vinnur fyrirspurnir á annan hátt, og rekstursskráning er ekki eins einföld og það sem við getum gert staðbundið. Því miður mun rack mini profiler eða venjuleg SQL-skrá ekki segja til um það. okkur allt og bendir ekki á hvaða hluti fyrirspurnarinnar ber ábyrgð á tilteknu tímabili. Í tilviki GraphQL-Ruby getum við notað viðskiptalausnir sem eru fáanlegar hér: https://graphql-ruby.org/queries/tracing, eða reyna að útbúa okkar eigin rekki. Hér að neðan lítur brotið út eins og staðbundinn rekki.

# lib/my_custom_tracer.rb
class MyCustomTracer  'graphql.lex',
    'parse' => 'graphql.parse',
    'validate' => 'graphql.validate',
    'analyze_query' => 'graphql.analyze_query',
    'analyze_multiplex' => 'graphql.analyze_multiplex',
    'execute_multiplex' => 'graphql.execute_multiplex',
    'execute_query' => 'graphql.execute_query',
    'execute_query_lazy' => 'graphql.execute_query_lazy'
  }

  def platform_trace(platform_key, key, _data, &block)
    start = ::Process.clock_gettime ::Process::CLOCK_MONOTONIC
    result = block.call
    duration = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - start
    observe(platform_key, key, duration)
    result
  end

  def platform_field_key(type, field)
    "graphql.#{type.graphql_name}.#{field.graphql_name}"
  end

  def platform_authorized_key(type)
    "graphql.authorized.#{type.graphql_name}"
  end

  def platform_resolve_type_key(type)
    "graphql.resolve_type.#{type.graphql_name}"
  end

  def observe(platform_key, key, duration)
    return if key == 'authorized'

 puts "platform_key: #{platform_key}, key: #{key}, duration: #{(duration * 1000).round(5)} ms".yellow
  end
end

Uppsetningin er einnig afar einföld, þú þarft að bæta rekjanleikaupplýsingum við skemað. slóðari (MyCustomTracer.new) stillingu. Eins og í dæminu hér að neðan:

# graphql-ruby/app/graphql/graphql_tutorial_schema.rb
class GraphqlTutorialSchema < GraphQL::Schema
  query Types::QueryType
  mutation Types::MutationType
  use GraphQL::Batch
  tracer(MyCustomTracer.new)
  ...
end

Úttakið úr slíkri rekjanlegri greiningu lítur svona út:

Hóf POST "/graphql" fyrir ::1 þann 2021-06-17 22:02:44 +0200
   (0.1ms)  SELECT sqlite_version(*)
Vinnsla af GraphqlController#execute sem */*
  Breytur: {"query"=>"{n  allLinks {n    idn    urln    descriptionn    createdAtn    postedBy {n idn namen links {n idn }n    }n  }n}", "graphql"=>{"query"=>"{n  allLinks {n    idn    urln    descriptionn    createdAtn    postedBy {n idn namen links {n idn }n    }n  }n}"}}
platform_key: graphql.lex, key: lex, duration: 0.156 ms
platform_key: graphql.parse, key: parse, duration: 0.108 ms
platform_key: graphql.validate, key: validate, duration: 0.537 ms
platform_key: graphql.analyze_query, key: analyze_query, duration: 0.123 ms
platform_key: graphql.analyze_multiplex, key: analyze_multiplex, duration: 0.159 ms
  Link Load (0.4ms)  SELECT "links".* FROM "links"
  ↳ app/graphql/graphql_tutorial_schema.rb:21:in `platform_trace'
platform_key: graphql.execute_query, key: execute_query, duration: 15.562 ms
  ↳ app/graphql/loaders/record_loader.rb:12:in `perform'
  ↳ app/graphql/loaders/association_loader.rb:46:in `preload_association'
platform_key: graphql.execute_query_lazy, key: execute_query_lazy, duration: 14.12 ms
platform_key: graphql.execute_multiplex, key: execute_multiplex, duration: 31.11 ms
Lokið 200 OK á 48ms (Skoðanir: 1.2ms | ActiveRecord: 2.0ms | Úthlutanir: 40128)

Yfirlit

GraphQL er ekki lengur ný tækni, en lausnir við vandamálum hennar eru ekki fullkomlega staðlaðar ef þær eru ekki hluti af bókasafninu. Innleiðing þessarar tækni í verkefni veitir margar tækifæri til að eiga samskipti við framenda og ég tel persónulega að þetta sé ný gæði í samanburði við það sem REST forritaskil býður upp á.

Af hverju þú ættir (líklega) að nota TypeScript

Hvernig á ekki að drepa verkefni með slæmum forritunarvenjum?

Stefnur við gagnaleit í NextJS

Tengdar greinar

Myndskreyting af heilbrigðisforriti fyrir snjallsíma með hjartatákni og hækkandi heilsufarsgrafík, merkt með The Codest-merkinu, sem táknar stafræna heilsu og HealthTech-lausnir.
Hugbúnaðarþróun

Heilbrigðis-hugbúnaður: gerðir og notkunartilvik

Tólin sem heilbrigðisstofnanir treysta á í dag líta ekkert út eins og pappírsskjöl frá fyrri áratugum. Heilbrigðisforrit styðja nú heilbrigðiskerfi, sjúklingameðferð og nútímalega heilbrigðisþjónustu á klínískum og...

THECODEST
Yfirlitsmynd sem sýnir hnignandi súlurit með uppstrekktri ör og gullmynt sem táknar kostnaðarhagkvæmni eða sparnað. The Codest-merkið birtist í efra vinstra horni með slagorðinu "In Code We Trust" á ljósgráum bakgrunni.
Hugbúnaðarþróun

Hvernig á að stækka þróunarteymið án þess að fórna gæðum vörunnar

Ertu að stækka þróunarteymið þitt? Lærðu hvernig á að vaxa án þess að fórna gæðum vörunnar. Þessi leiðarvísir fjallar um merki um að kominn sé tími til að stækka, uppbyggingu teymisins, ráðningar, forystu og verkfæri—og hvernig teymið getur...

THECODEST
Hugbúnaðarþróun

Búðu til vefumsóknir sem þola framtíðina: innsýn frá sérfræðiteymi The Codest

Uppgötvaðu hvernig The Codest skarar fram úr við að búa til stigstækar, gagnvirkar vefumsóknir með nýjustu tækni, sem bjóða upp á hnökralausa notendaupplifun á öllum kerfum. Lærðu hvernig sérfræðiþekking okkar knýr fram stafræna umbreytingu og viðskipti...

THECODEST
Hugbúnaðarþróun

Topp 10 hugbúnaðarþróunarfyrirtæki í Lettlandi

Kynntu þér fremstu hugbúnaðarþróunarfyrirtæki Lettlands og nýstárlegar lausnir þeirra í nýjustu grein okkar. Uppgötvaðu hvernig þessir tækniforingjar geta hjálpað til við að efla fyrirtækið þitt.

thecodest
Lausnir fyrir fyrirtæki og vaxtarfyrirtæki

Grunnatriði í Java hugbúnaðarþróun: Leiðarvísir að árangursríkri útvistun

Kannaðu þessa ómissandi leiðbeiningu um árangursríka outsourcing Java hugbúnaðarþróun til að auka skilvirkni, afla aðgangs að sérfræðiþekkingu og tryggja árangur verkefna með The Codest.

thecodest

Gerðu þig áskrifanda að þekkingargrunni okkar og vertu upplýstur um sérfræðiþekkingu upplýsingatæknigeirans.

    Um okkur

    The Codest – Alþjóðlegt hugbúnaðarþróunarfyrirtæki með tæknimiðstöðvar í Póllandi.

    Bretland - Höfuðstöðvar

    • Skrifstofa 303B, 182-184 High Street North E6 2JA
      Lundúnir, England

    Pólland - staðbundin tæknimiðstöðvar

    • Fabryczna skrifstofugarður, Aleja
      Herbergi 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Varsjá, Pólland

    The Codest

    • Heim
    • Um okkur
    • Þjónusta
    • Case Studies
    • Vitið hvernig
    • Starfsferilmöguleikar
    • Orðabók

    Þjónusta

    • Það er ráðgjafi
    • Hugbúnaðarþróun
    • Bakendaþróun
    • Framhliðþróun
    • Staff Augmentation
    • Bakhliðaráþróunaraðilar
    • Skýjaverkfræðingar
    • Gagnaverkfræðingar
    • Annað
    • Gæðatryggingartæknimenn

    Auðlindir

    • Staðreyndir og goðsagnir um samstarf við utanaðkomandi hugbúnaðarþróunaraðila
    • Frá Bandaríkjunum til Evrópu: Af hverju ákveða bandarísk sprotafyrirtæki að flytja til Evrópu?
    • Samanburður á tæknifjarkerfisþróunarmiðstöðvum: Tech Offshore Europe (Pólland), ASEAN (Filippseyjar), Eurasia (Tyrkland)
    • Hvert eru helstu áskoranir CTO-a og CIO-a?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Höfundarréttur © 2026 af The Codest. Öll réttindi áskilin.

    is_ISIcelandic
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian es_ESSpanish nl_NLDutch etEstonian elGreek pt_PTPortuguese cs_CZCzech lvLatvian lt_LTLithuanian is_ISIcelandic