sql - 优化sql查询

标签 sql optimization oracle11g

我的程序核心中有一个巨大的遗留查询, 查询花费了太多时间,让它运行得更快的最佳方法是什么? 我用的是 oracle 11g

 SELECT   *
     FROM     ( SELECT  COUNT(*) AS countme,
                       string_value        ,
                       name                ,
                       property_id         ,
                       category_id
              FROM    ( SELECT DISTINCT a.string_value,
                                        a.name        ,
                                        a.property_id ,
                                        b.product_id  ,
                                        a.category_id
                       FROM             filter_criterias a
                                        JOIN product_properties b
                                        ON              (
                                                                          a.property_id = b.property_id
                                                         AND
                                                                          (
                                                                                           (
                                                                                                            isnumber(b.value)        IS NOT NULL
                                                                                           AND              isnumber(a.range_bottom) IS NOT NULL
                                                                                           AND              isnumber(a.range_top)    IS NOT NULL
                                                                                           AND
                                                                                                            (
                                                                                                                             a.range_bottom >a.range_top
                                                                                                            AND              b.value       >= a.range_bottom
                                                                                                            OR               a.range_bottom<=a.range_top
                                                                                                            AND              b.value       >= a.range_bottom
                                                                                                            AND              b.value       <=a.range_top
                                                                                                            )
                                                                                           )
                                                                          )
                                                         )
                                        JOIN PRODUCT_CATEGORY prc
                                        ON               (
                                                                          prc.sku         = b.product_id
                                                         AND              prc.category_id = a.category_id
                                                         )
                                        JOIN PRODUCT pr
                                        ON               (
                                                                          b.product_id = pr.SKU
                                                         AND              pr.visible   = '1'
                                                         )
                       )
              GROUP BY (string_value, name, property_id,category_id)

              UNION

              SELECT   COUNT(*) AS countme,
                       string_value       ,
                       name               ,
                       property_id        ,
                       category_id
              FROM    ( SELECT DISTINCT a.string_value,
                                        a.name        ,
                                        a.property_id ,
                                        b.product_id  ,
                                        a.category_id
                       FROM             filter_criterias a
                                        JOIN product_properties b
                                        ON              (
                                                                          a.property_id = b.property_id
                                                         AND
                                                                          (
                                                                                           (
                                                                                                            a.name= b.value
                                                                                           )
                                                                          )
                                                         )
                                        JOIN PRODUCT_CATEGORY prc
                                        ON               (
                                                                          prc.sku         = b.product_id
                                                         AND              prc.category_id = a.category_id
                                                         )
                                        JOIN PRODUCT pr
                                        ON               (
                                                                          b.product_id = pr.SKU
                                                         AND              pr.visible   = '1'
                                                         )
                       )
              GROUP BY (string_value, name, property_id,category_id)
              )
     ORDER BY 5,4,3,2

这是解释计划

    "Optimizer" "Cost"  "Cardinality"   "Bytes" "Partition Start"   "Partition Stop"    "Partition Id"  "ACCESS PREDICATES" "FILTER PREDICATES"
"SELECT STATEMENT"  "ALL_ROWS"      "1298"  "2"         "542"   ""  ""  ""  ""  ""
"SORT(ORDER BY)"    ""              "1298"  "2"         "542"   ""  ""  ""  ""  ""
"VIEW"              ""              "1297"  "2"         "542"   ""  ""  ""  ""  ""
"SORT(UNIQUE)"      ""              "1297"  "2"         "74"    ""  ""  ""  ""  ""
"UNION-ALL" ""      ""              ""  ""  ""          ""  ""  ""  ""
"HASH(GROUP BY)"    ""              "661"   "1"         "37"    ""  ""  ""  ""  ""
"VIEW"              ""              "659"   "1"         "37"    ""  ""  ""  ""  ""
"HASH(UNIQUE)"      ""              "659"   "1"         "95"    ""  ""  ""  ""  ""
"NESTED LOOPS"      ""              ""  ""  ""          ""  ""  ""  ""  ""
"NESTED LOOPS"      ""              "658"   "1"         "95"    ""  ""  ""  ""  ""
"HASH JOIN"         ""              "493"   "1"         "81"    ""  ""  ""  ""B"."PRODUCT_ID"=TO_NUMBER("PRC"."SKU") AND "A"."CATEGORY_ID"=SYS_OP_C2C("PRC"."CATEGORY_ID")" ""
"HASH JOIN"         ""              "369"   "2"         "128"   ""  ""  ""  ""B"."PROPERTY_ID"=TO_NUMBER("A"."PROPERTY_ID")"    ""A"."RANGE_BOTTOM">"A"."RANGE_TOP" AND "A"."RANGE_BOTTOM"<=TO_NUMBER("B"."VALUE") OR "A"."RANGE_BOTTOM"<="A"."RANGE_TOP" AND "A"."RANGE_BOTTOM"<=TO_NUMBER("B"."VALUE") AND "A"."RANGE_TOP">=TO_NUMBER("B"."VALUE")"
"TABLE ACCESS(FULL) BNET.B_FILTER_CRITERIAS"    "ANALYZED"  "36"    "28"    "1148"  ""  ""  ""  ""  ""ISNUMBER"(TO_CHAR("A"."RANGE_BOTTOM")) IS NOT NULL AND "ISNUMBER"(TO_CHAR("A"."RANGE_TOP")) IS NOT NULL"
"TABLE ACCESS(FULL) BNET.B_PRODUCT_PROPERTIES"  "ANALYZED"  "332"   "12566" "289018"    ""  ""  ""  ""  ""ISNUMBER"("B"."VALUE") IS NOT NULL"
"TABLE ACCESS(FULL) BNET.WLCS_PRODUCT_CATEGORY" "ANALYZED"  "124"   "129762"    "2205954"   ""  ""  ""  ""  ""
"INDEX(RANGE SCAN) BNET.WLCS_PROD_VISIBLE_IDX"  "ANALYZED"  "12"    "6208"  ""  ""  ""  ""  ""PR"."VISIBLE"='1'"    ""
"TABLE ACCESS(BY INDEX ROWID) BNET.WLCS_PRODUCT"    "ANALYZED"  "164"   "1" "14"    ""  ""  ""  ""  ""B"."PRODUCT_ID"=TO_NUMBER("PR"."SKU")"
"HASH(GROUP BY)"    ""              "637"   "1"         "37"    ""  ""  ""  ""  ""
"VIEW"              ""              "635"   "1"         "37"    ""  ""  ""  ""  ""
"HASH(UNIQUE)"      ""              "635"   "1"         "91"    ""  ""  ""  ""  ""
"HASH JOIN"         ""              "634"   "1"         "91"    ""  ""  ""  ""B"."PRODUCT_ID"=TO_NUMBER("PRC"."SKU") AND "A"."CATEGORY_ID"=SYS_OP_C2C("PRC"."CATEGORY_ID")" ""
"NESTED LOOPS"      ""              ""      ""  ""  ""  ""  ""  ""  ""
"NESTED LOOPS"      ""              "509"   "1"         "74"    ""  ""  ""  ""  ""
"HASH JOIN"         ""              "345"   "1"         "60"    ""  ""  ""  ""B"."PROPERTY_ID"=TO_NUMBER("A"."PROPERTY_ID") AND "A"."NAME"="B"."VALUE"" ""
"TABLE ACCESS(FULL) BNET.B_FILTER_CRITERIAS"    "ANALYZED"  "35"    "11257" "416509"    ""  ""  ""  ""  ""
"TABLE ACCESS(FULL) BNET.B_PRODUCT_PROPERTIES"  "ANALYZED"  "309"   "251319"    "5780337"   ""  ""  ""  ""  ""
"INDEX(RANGE SCAN) BNET.WLCS_PROD_VISIBLE_IDX"  "ANALYZED"  "12"    "6208"  ""  ""  ""  ""  ""PR"."VISIBLE"='1'"    ""
"TABLE ACCESS(BY INDEX ROWID) BNET.WLCS_PRODUCT"    "ANALYZED"  "164"   "1" "14"    ""  ""  ""  ""  ""B"."PRODUCT_ID"=TO_NUMBER("PR"."SKU")"
"TABLE ACCESS(FULL) BNET.WLCS_PRODUCT_CATEGORY" "ANALYZED"  "124"   "129762"    "2205954"   ""  ""  ""  ""  ""

最佳答案

一个潜在的大量问题来源是您必须使用 ISNUMBER。

如果将数值存储为文本,然后使用诸如“x <= y”之类的操作,就会完成很多负面的事情:
- 字符串在使用前必须解析为数字
- 字符串的索引可能与数字的索引没有相似之处
- 如果索引没用,你会得到表扫描而不是索引搜索

我强烈建议将值存储为实数,而不是字符串。不必使用 ISNUMBER,不必转换每个值,因此实际上能够使用索引可以带来极大的性能优势。

编辑

您刚刚添加的 PLAN 包含许多 TABLE ACCESS(FULL) 实例,其中一些似乎与存储为字符串的数值相关联。

关于sql - 优化sql查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6985487/

相关文章:

java - 如何使用map来减少Spring MVC Web应用程序中的对象创建?

SQL Merge 语句适用于 Oracle 11g 但不适用于 9i

sql - PIVOT 语句是否有 ANSI 规范?

android - 以字符串形式读取文件

javascript - (JavaScript) 如何在 Phaser 3 中将图像定义为变量

java - 4 小时后不应访问 Otp

mysql - On 子句中的未知列(但确实存在)

MySQL查询以获得特定排名

c# - groupby 之后的 linq 无法获取列值

sql - 如何在 PostgreSQL 中的引用表上创建具有约束的外键