3

Django でリモートの Oracle サーバーに対して生の SQL クエリを実行しています。クエリは非常に長く、完了までに 1 分半かかりましたが、Oracle SQL Server プログラムを使用して同じクエリを実行すると、クエリは 1 秒未満で実行されます。

なぜこれほどまでに性能差があるのでしょうか。Django でクエリを高速化するにはどうすればよいですか?

ところで、私は Django の開発サーバーとプロファイル ツールバー (Django 1.5) を使用しています。

更新: Djangoのクエリは次のとおりです

holidays_filter = ''
if filters['holidays'] == 'exclude':
    holidays_filter = 'AND FECHAS.FESTIVO = 0'

hp_inner_join = ''
if filters['hour-mode'] == 'hp-sector-ps':
    hp_inner_join = """
        INNER JOIN
        EGW.RHP_CELLSEC_PS HPCELLPS
        ON UCELL2.DIA = HPCELLPS.DIA
           AND UCELL2.HORA = HPCELLPS.HORA
           AND UCELL2.RNC = HPCELLPS.RNC
           AND UCELL2.UTRANCELL = HPCELLPS.CELLID
        """
elif filters['hour-mode'] == 'hp-rnc-ps':    
    hp_inner_join = """
        INNER JOIN
        EGW.RHP_RNC_PS HPRNCPS
        ON UCELL2.DIA = HPRNCPS.DIA
           AND UCELL2.HORA = HPRNCPS.HORA
           AND UCELL2.RNC = HPRNCPS.RNC
        """

sql = """
  SELECT CUSTOM.DIA, CUSTOM.HORA,
         ROUND(CUSTOM.TRAF_CS57 + CUSTOM.TRAF_CS64 + CUSTOM.TRAF_CS12 + CUSTOM.TRAF_CSAMR12200 + CUSTOM.TRAF_CSAMR7950 + CUSTOM.TRAF_CSAMR5900 + CUSTOM.TRAF_CSAMR4750, 1) AS TRAFICO_CS_ERL,
         ROUND(CUSTOM.A + CUSTOM.B + CUSTOM.C + CUSTOM.D, 1) AS TRAFICO_PS_ERL

    FROM (SELECT TOTAL.DIA, TOTAL.HORA, TOTAL.RNC, TOTAL.UTRANCELL,
                 CASE
                     WHEN TOTAL.PMSAMPLESCS12RABESTABLISH = 0
                     THEN 0
                     ELSE TOTAL.PMSUMCS12RABESTABLISH / TOTAL.PMSAMPLESCS12RABESTABLISH
                 END AS TRAF_CS12,
                 CASE
                     WHEN TOTAL.PMSAMPLESBESTCS57RABESTABLISH = 0
                     THEN 0
                     ELSE TOTAL.PMSUMBESTCS57RABESTABLISH / TOTAL.PMSAMPLESBESTCS57RABESTABLISH
                 END AS TRAF_CS57,
                 CASE
                     WHEN TOTAL.PMSAMPLESBESTCS64RABESTABLISH = 0
                     THEN 0
                     ELSE TOTAL.PMSUMBESTCS64RABESTABLISH / TOTAL.PMSAMPLESBESTCS64RABESTABLISH
                 END AS TRAF_CS64,
                 CASE
                     WHEN TOTAL.PMSAMPLBESTAMR12200RABESTABLIS = 0
                     THEN 0
                     ELSE TOTAL.PMSUMBESTAMR12200RABESTABLISH / TOTAL.PMSAMPLBESTAMR12200RABESTABLIS
                 END AS TRAF_CSAMR12200,
                 CASE
                     WHEN TOTAL.PMSAMPLBESTAMR7950RABESTABLISH = 0
                     THEN 0
                     ELSE TOTAL.PMSUMBESTAMR7950RABESTABLISH / TOTAL.PMSAMPLBESTAMR7950RABESTABLISH
                 END AS TRAF_CSAMR7950,
                 CASE
                     WHEN TOTAL.PMSAMPLBESTAMR5900RABESTABLISH = 0
                     THEN 0
                     ELSE TOTAL.PMSUMBESTAMR5900RABESTABLISH / TOTAL.PMSAMPLBESTAMR5900RABESTABLISH
                 END AS TRAF_CSAMR5900,
                 CASE
                     WHEN TOTAL.PMSAMPLBESTAMR4750RABESTABLISH = 0
                     THEN 0
                     ELSE TOTAL.PMSUMBESTAMR4750RABESTABLISH / TOTAL.PMSAMPLBESTAMR4750RABESTABLISH
                 END AS TRAF_CSAMR4750,

                 CASE
                     WHEN TOTAL.PMSAMPLEBESTDCHPSINTRABESTABLI = 0
                     THEN 0
                     ELSE TOTAL.PMSUMBESTDCHPSINTRABESTABLISH / TOTAL.PMSAMPLEBESTDCHPSINTRABESTABLI
                 END AS A,
                 CASE
                     WHEN TOTAL.PMSAMPLEFACHPSINTRABESTABLISH = 0
                     THEN 0
                     ELSE TOTAL.PMSUMFACHPSINTRABESTABLISH / TOTAL.PMSAMPLEFACHPSINTRABESTABLISH
                 END AS B,
                 CASE
                     WHEN TOTAL.PMSAMPBESTPSHSADCHRABESTABLISH = 0
                     THEN 0
                     ELSE TOTAL.PMSUMBESTPSHSADCHRABESTABLISH / TOTAL.PMSAMPBESTPSHSADCHRABESTABLISH
                 END AS C,
                 CASE
                     WHEN TOTAL.PMSAMPLBESTPSEULRABESTABLI = 0
                     THEN 0
                     ELSE TOTAL.PMSUMBESTPSEULRABESTABLISH / TOTAL.PMSAMPLBESTPSEULRABESTABLI
                 END AS D

            FROM (SELECT UCELL2.DIA, UCELL2.HORA, UCELL2.RNC, UCELL2.UTRANCELL,
                         SUM(UCELL2.PMSAMPLESCS12RABESTABLISH) AS PMSAMPLESCS12RABESTABLISH,
                         SUM(UCELL2.PMSUMCS12RABESTABLISH) AS PMSUMCS12RABESTABLISH,
                         SUM(UCELL3.PMSAMPLESBESTCS57RABESTABLISH) AS PMSAMPLESBESTCS57RABESTABLISH,
                         SUM(UCELL3.PMSUMBESTCS57RABESTABLISH) AS PMSUMBESTCS57RABESTABLISH,
                         SUM(UCELL3.PMSAMPLESBESTCS64RABESTABLISH) AS PMSAMPLESBESTCS64RABESTABLISH,
                         SUM(UCELL3.PMSUMBESTCS64RABESTABLISH) AS PMSUMBESTCS64RABESTABLISH,
                         SUM(UCELL3.PMSUMBESTDCHPSINTRABESTABLISH) AS PMSUMBESTDCHPSINTRABESTABLISH,
                         SUM(UCELL3.PMSAMPLEBESTDCHPSINTRABESTABLI) AS PMSAMPLEBESTDCHPSINTRABESTABLI,
                         SUM(UCELL3.PMSUMFACHPSINTRABESTABLISH) AS PMSUMFACHPSINTRABESTABLISH,
                         SUM(UCELL3.PMSAMPLEFACHPSINTRABESTABLISH) AS PMSAMPLEFACHPSINTRABESTABLISH,
                         SUM(UCELL3.PMSUMBESTPSHSADCHRABESTABLISH) AS PMSUMBESTPSHSADCHRABESTABLISH,
                         SUM(UCELL3.PMSAMPBESTPSHSADCHRABESTABLISH) AS PMSAMPBESTPSHSADCHRABESTABLISH,
                         SUM(UCELL3.PMSUMBESTPSEULRABESTABLISH) AS PMSUMBESTPSEULRABESTABLISH,
                         SUM(UCELL3.PMSAMPLBESTPSEULRABESTABLI) AS PMSAMPLBESTPSEULRABESTABLI,
                         SUM(UCELL4.PMSAMPLBESTAMR12200RABESTABLIS) AS PMSAMPLBESTAMR12200RABESTABLIS,
                         SUM(UCELL4.PMSUMBESTAMR12200RABESTABLISH) AS PMSUMBESTAMR12200RABESTABLISH,
                         SUM(UCELL4.PMSAMPLBESTAMR7950RABESTABLISH) AS PMSAMPLBESTAMR7950RABESTABLISH,
                         SUM(UCELL4.PMSUMBESTAMR7950RABESTABLISH) AS PMSUMBESTAMR7950RABESTABLISH,
                         SUM(UCELL4.PMSAMPLBESTAMR5900RABESTABLISH) AS PMSAMPLBESTAMR5900RABESTABLISH,
                         SUM(UCELL4.PMSUMBESTAMR5900RABESTABLISH) AS PMSUMBESTAMR5900RABESTABLISH,
                         SUM(UCELL4.PMSAMPLBESTAMR4750RABESTABLISH) AS PMSAMPLBESTAMR4750RABESTABLISH,
                         SUM(UCELL4.PMSUMBESTAMR4750RABESTABLISH) AS PMSUMBESTAMR4750RABESTABLISH

                    FROM EGW.TF_RNC_RAN_UCELL2 UCELL2

                         INNER JOIN
                         EGW.TF_RNC_RAN_UCELL3 UCELL3
                         ON UCELL2.DIA = UCELL3.DIA
                            AND UCELL2.HORA = UCELL3.HORA
                            AND UCELL2.RNC = UCELL3.RNC
                            AND UCELL2.MO = UCELL3.MO
                            AND UCELL2.MINUTO = UCELL3.MINUTO
                            AND UCELL2.UTRANCELL = UCELL3.UTRANCELL

                         INNER JOIN
                         EGW.TF_RNC_RAN_UCELL4 UCELL4
                         ON UCELL2.DIA = UCELL4.DIA
                            AND UCELL2.HORA = UCELL4.HORA
                            AND UCELL2.RNC = UCELL4.RNC
                            AND UCELL2.MO = UCELL4.MO
                            AND UCELL2.MINUTO = UCELL4.MINUTO
                            AND UCELL2.UTRANCELL = UCELL4.UTRANCELL

                         INNER JOIN
                         JANO.FECHAS FECHAS
                         ON UCELL2.DIA = FECHAS.FECHA

                         """ + hp_inner_join + """

                   WHERE UCELL2.DIA BETWEEN TO_DATE(%s, 'YYYY-MM-DD') AND TO_DATE(%s, 'YYYY-MM-DD')
                     AND UCELL2.HORA BETWEEN %s AND %s
                     AND UCELL2.RNC = %s
                     AND UCELL2.UTRANCELL = %s
                     AND FECHAS.DIASEM IN (%s,%s,%s,%s,%s,%s,%s) 
                     """ + holidays_filter + """

                GROUP BY UCELL2.DIA, UCELL2.HORA, UCELL2.RNC, UCELL2.UTRANCELL) TOTAL) CUSTOM

ORDER BY CUSTOM.DIA, CUSTOM.HORA        
"""
4

2 に答える 2

1

違いを確認するには、Explain Plan を使用して両方のクエリを実行する必要があります。私の推測では、リテラル パラメーターの場合はインデックスが使用され、バインドされたパラメーターの場合は使用されない可能性があります。2 つの違いがわかる場合は、select ステートメントに「ヒント」句を追加して、正しいインデックスを強制的に選択する必要がある場合があります。ここでヒントについて読むことができます

sqlplus を使用している場合は、autotrace をオンにして、Explain Plan と実行統計を表示できます。次に例を示します。

SQL> set autotrace on
SQL> set linesize 200
SQL> set serveroutput on
SQL> spool foo.log
SQL> select count(*) from ucbcust; -- this is just a test table in my database. replace with your SQL.
SQL>   ... output shows...
SQL>  spool off


Output would look something like this (obviously, different for your query):



  Execution Plan
    ----------------------------------------------------------                                  
    Plan hash value: 1527793343                                                                                           ----------------------------------------------------------------------------------------          
    | Id  | Operation             | Name                   | Rows  | Cost (%CPU)| Time     |            

     ----------------------------------------------------------------------------------------         

| | 0 | ステートメントを選択 | | | 1 | 3 (0)| 00:00:01 | 1 | ソート集計 | | | 1 | | |
| | 2 | インデックス高速フルスキャン| UCBCUST_CUST_KEY_INDEX | 2088年 | 3 (0)| 00:00:01

|                                                                                                    ----------------------------------------------------------------------------------------
    Statistics

              0  recursive calls                                                                                                                                                                            
              0  db block gets                                                                                                                                                                              
             17  consistent gets                                                                                                                                                                            
              0  physical reads                                                                                                                                                                             
              0  redo size                                                                                                                                                                                  
            343  bytes sent via SQL*Net to client                                                                                                                                                           
            364  bytes received via SQL*Net from client                                                                                                                                                     
              2  SQL*Net roundtrips to/from client                                                                                                                                                          
              0  sorts (memory)                                                                                                                                                                             
              0  sorts (disk)                                                                                                                                                                               
              1  rows processed                                                                                                                                                                             

sqlplus で同様の方法でパラメーター化されたクエリを実行するには、変数をプレースホルダーとして定義する必要があります。例:

SQL> variable foo number
SQL> exec :foo := 1000

PL/SQL procedure successfully completed.

SQL> select :foo from dual
  2  /

      :FOO
----------
      1000

そのため、クエリですべての「%*」パラメーターを変数に置き換え、Sqlplus で実行して実行の詳細を確認します。これらのツールを使用すると、実行計画の違いがわかるはずです。

于 2013-06-03T20:38:34.020 に答える