sql >> Database >  >> RDS >> Mysql

Hoe bouwt Rails een MySQL-statement?

sql proberen?

Als het alleen deze ene verklaring is, en het veroorzaakt productieproblemen, kun je de querygenerator dan even weglaten? Met andere woorden, voor zeer korte termijn, schrijf gewoon zelf de SQL. Hiermee win je wat tijd.

# All on one line:
Artist.find_by_sql
  "SELECT `artists`.* FROM `artists` 
   WHERE `artists`.`id` = #{params[:artist_id].to_i} LIMIT 1"

ARel/MySQL uitleggen?

Rails kan helpen uitleggen wat MySQL probeert te doen:

Artist.find(params[:artist_id]).explain

http://weblog.rubyonrails.org/2011/12/6/what-s-new-in-edge-rails-explain/

Misschien kun je een soort verschil ontdekken tussen de zoekopdrachten die slagen en die falen, zoals hoe de explain gebruikt indexen of optimalisaties.

mysql2-juweeltje?

Kun je proberen over te stappen van de mysql-edelsteen naar de mysql2-edelsteen? Welke storing krijg je als je overschakelt naar de mysql2-edelsteen?

volatiliteit?

Misschien is er iets anders dat de params-hash on-the-fly verandert, dus je ziet het wanneer je het afdrukt, maar het is veranderd tegen de tijd dat de query wordt uitgevoerd?

Probeer de variabele toe te wijzen zodra je de parameters hebt ontvangen:

artist_id = params[:artist_id]
... whatever code here...
@artist = Artist.find(artist_id)

niet de params-hash?

Je schreef:"Betekenis Rails komt niet voorbij in de params [:artist_id] wat duidelijk in de params-hash staat." Ik denk niet dat dat het probleem is -- ik verwacht dat je dit ziet omdat Rails de "?" als tijdelijke aanduiding voor een voorbereide verklaring.

Om erachter te komen, voert u de door @Mori voorgestelde opdrachten uit en vergelijkt u ze; ze zouden hetzelfde moeten zijn.

Article.find(42).to_sql
Article.find(params[:artist_id]).to_sql

voorbereide verklaringen?

Het kan een voorbereid cache-probleem zijn, wanneer de query daadwerkelijk wordt uitgevoerd.

Dit is de code die niet werkt -- en er is een dikke waarschuwing.

begin
  stmt.execute(*binds.map { |col, val| type_cast(val, col) })
rescue Mysql::Error => e
  # Older versions of MySQL leave the prepared statement in a bad
  # place when an error occurs. To support older mysql versions, we
  # need to close the statement and delete the statement from the
  # cache.
  stmt.close
  @statements.delete sql
  raise e
end

Probeer uw database te configureren om voorbereide instructies uit te schakelen, om te zien of dat een verschil maakt.

In uw ./config/database.yml bestand:

production:
   adapter: mysql
   prepared_statements: false
   ...

bugs met voorbereide statements?

Er kan een probleem zijn met Rails die deze instelling negeert. Als je er veel meer over wilt weten, bekijk dan deze discussie en bugfix door Jeremey Cole en Aaron:https://github.com/rails/rails/pull/7042

Heroku kan de instelling negeren. Hier is een manier waarop je Heroku kunt overschrijven door de setup van prepare_statements te patchen:https://github.com /rails/rails/issues/5297

de querycache verwijderen?

Probeer de ActiveRecord QueryCache te verwijderen om te zien of dat een verschil maakt:

config.middleware.delete ActiveRecord::QueryCache

http://edgeguides.rubyonrails.org/configuring.html#configuring-middle

postgres proberen?

Als je Postgres kunt proberen, kan dat het ook ophelderen. Dat is misschien geen langetermijnoplossing voor u, maar het zou het probleem isoleren naar MySQL.



  1. Een query schrijven met meerdere gedragingen

  2. Eenvoudig een webserver instellen met XAMPP

  3. Probeer Tijd naar Sec te converteren in Oracle SQL

  4. Hash-joins op nullable-kolommen