有史以来最大的景观!怎样才能减少这个怪物??

发布于 2024-10-07 06:39:35 字数 3466 浏览 0 评论 0原文

曾几何时,有一个具有许多连接的视图:

CREATE VIEW [dbo].[V_BIGGEST_VIEW_EVER]
AS
SELECT {many many columns}
FROM (SELECT * FROM dbo.T_CUS_TSK_TASK WHERE is_deleted=0) T
  INNER JOIN dbo.V_CUS_GRP_GROUP G ON (T.group_id = G.group_id)
  INNER JOIN dbo.T_BKK_DISCOUNT_TYPE DT ON (DT.discount_type_id=T.discount_type_id)
  INNER JOIN dbo.T_BKK_CURRENCY DC ON (T.debit_currency_id=DC.currency_id)
  INNER JOIN dbo.T_BKK_CURRENCY PC ON (T.payback_currency_id=PC.currency_id)
  INNER JOIN dbo.T_BKK_CURRENCY FC ON (T.final_debit_currency_id=FC.currency_id)
  INNER JOIN dbo.T_GLOBAL_COUNTER D1C ON (D1C.company_id=T.company_id AND
    D1C.counter_name='PROFORMA_INVOICE_COUNTER')
  INNER JOIN dbo.T_GLOBAL_COUNTER D2C ON (D2C.company_id=T.company_id AND
    D2C.counter_name='TAX_INVOICE_COUNTER')
  INNER JOIN dbo.T_GLOBAL_COUNTER D3C ON (D3C.company_id=T.company_id AND
    D3C.counter_name='INVOICE_RECEIPT_COUNTER')
  INNER JOIN dbo.T_GLOBAL_COUNTER D4C ON (D4C.company_id=T.company_id AND
    D4C.counter_name='DELIVERY_NOTE_COUNTER')
  INNER JOIN dbo.T_GLOBAL_COUNTER D5C ON (D5C.company_id=T.company_id AND
    D5C.counter_name='BILL_OF_LADING_COUNTER')
  INNER JOIN dbo.T_GLOBAL_COUNTER D6C ON (D6C.company_id=T.company_id AND
    D6C.counter_name='CREDIT_INVOICE_COUNTER')
  LEFT JOIN dbo.V_SYS_BRANCH BR ON (T.branch_id = BR.branch_id)
  LEFT JOIN dbo.T_CUS_TSK_TASKS_ARRAY AR ON (T.array_id = AR.array_id)
  LEFT JOIN dbo.T_DRIVER D ON (T.driver_id = D.driver_id)
  LEFT JOIN dbo.T_VEHICLE V ON (T.vehicle_id = V.vehicle_id)
  LEFT JOIN dbo.T_STF_INVITER I ON (T.inviter_id = I.inviter_id)
  LEFT JOIN dbo.T_STF_SUBCONTRACTOR SC1 ON (SC1.subcontractor_id = D.subcontractor_id)
  LEFT JOIN dbo.T_STF_SUBCONTRACTOR SC2 ON (SC2.subcontractor_id = T.subcontractor_id)
  LEFT JOIN dbo.T_CUS_TSK_TASK_STATUS S ON (S.task_status_id=T.task_status_id)
  LEFT JOIN dbo.V_STF_SUB_LOCATION SL1 ON (SL1.sub_location_id=T.start_sub_location_id)
  LEFT JOIN dbo.V_STF_SUB_LOCATION SL2 ON (SL2.sub_location_id=T.end_sub_location_id)
  LEFT JOIN dbo.T_STF_CUSTOMER CU ON (CU.customer_id=T.customer_id)
  LEFT JOIN dbo.T_STF_CUSTOMER_SPLITTING_CODE SP ON (SP.splitting_id=T.splitting_id)
  LEFT JOIN dbo.V_CUS_TSK_CREDIT_FOR_TASK CR ON CR.task_id=T.task_id
  LEFT JOIN dbo.T_BKK_PROFORMA_INVOICE D1 ON (T.proforma_invoice_id=D1.proforma_invoice_id)
  LEFT JOIN dbo.T_BKK_TAX_INVOICE D2 ON (T.tax_invoice_id=D2.tax_invoice_id)
  LEFT JOIN dbo.T_BKK_INVOICE_RECEIPT D3 ON (T.invoice_receipt_id=D3.invoice_receipt_id)
  LEFT JOIN dbo.T_BKK_DELIVERY_NOTE D4 ON (T.delivery_note_id=D4.delivery_note_id)
  LEFT JOIN dbo.T_BKK_BILL_OF_LADING D5 ON (T.bill_of_lading_id=D5.bill_of_lading_id)
  LEFT JOIN dbo.V_CUS_TSK_CONTAINER CONTAINER1 ON (CONTAINER1.container_id=T.container1_id)
  LEFT JOIN dbo.V_CUS_TSK_CONTAINER CONTAINER2 ON (CONTAINER2.container_id=T.container2_id)
  LEFT JOIN dbo.V_STF_TRAILER TRAILER1 ON (TRAILER1.trailer_id=T.trailer1_id)
  LEFT JOIN dbo.V_STF_TRAILER TRAILER2 ON (TRAILER2.trailer_id=T.trailer2_id)
  LEFT JOIN dbo.T_STF_LUGGAGE_TYPE LUGGAGE_TYPE ON (LUGGAGE_TYPE.luggage_type_id=T.luggage_type_id)

有一天,用户向视图请求查询:

SELECT {many many columns}
FROM V_BIGGEST_VIEW_EVER
WHERE {column1}=1 AND
      {column2}=2 AND
      .......
      {and so and so}
      .......
      {columnN}=N

而懒惰的最大视图-曾经工作过,工作过,之后 5 分钟(!!)不少于它返回结果。

这些表有主键和外键。

如何减少查询执行时间? 我怎样才能减少这种观点?

我在谷歌上搜索,但找不到任何有帮助的东西。

Once upon a time there was a View with many many Joins:

CREATE VIEW [dbo].[V_BIGGEST_VIEW_EVER]
AS
SELECT {many many columns}
FROM (SELECT * FROM dbo.T_CUS_TSK_TASK WHERE is_deleted=0) T
  INNER JOIN dbo.V_CUS_GRP_GROUP G ON (T.group_id = G.group_id)
  INNER JOIN dbo.T_BKK_DISCOUNT_TYPE DT ON (DT.discount_type_id=T.discount_type_id)
  INNER JOIN dbo.T_BKK_CURRENCY DC ON (T.debit_currency_id=DC.currency_id)
  INNER JOIN dbo.T_BKK_CURRENCY PC ON (T.payback_currency_id=PC.currency_id)
  INNER JOIN dbo.T_BKK_CURRENCY FC ON (T.final_debit_currency_id=FC.currency_id)
  INNER JOIN dbo.T_GLOBAL_COUNTER D1C ON (D1C.company_id=T.company_id AND
    D1C.counter_name='PROFORMA_INVOICE_COUNTER')
  INNER JOIN dbo.T_GLOBAL_COUNTER D2C ON (D2C.company_id=T.company_id AND
    D2C.counter_name='TAX_INVOICE_COUNTER')
  INNER JOIN dbo.T_GLOBAL_COUNTER D3C ON (D3C.company_id=T.company_id AND
    D3C.counter_name='INVOICE_RECEIPT_COUNTER')
  INNER JOIN dbo.T_GLOBAL_COUNTER D4C ON (D4C.company_id=T.company_id AND
    D4C.counter_name='DELIVERY_NOTE_COUNTER')
  INNER JOIN dbo.T_GLOBAL_COUNTER D5C ON (D5C.company_id=T.company_id AND
    D5C.counter_name='BILL_OF_LADING_COUNTER')
  INNER JOIN dbo.T_GLOBAL_COUNTER D6C ON (D6C.company_id=T.company_id AND
    D6C.counter_name='CREDIT_INVOICE_COUNTER')
  LEFT JOIN dbo.V_SYS_BRANCH BR ON (T.branch_id = BR.branch_id)
  LEFT JOIN dbo.T_CUS_TSK_TASKS_ARRAY AR ON (T.array_id = AR.array_id)
  LEFT JOIN dbo.T_DRIVER D ON (T.driver_id = D.driver_id)
  LEFT JOIN dbo.T_VEHICLE V ON (T.vehicle_id = V.vehicle_id)
  LEFT JOIN dbo.T_STF_INVITER I ON (T.inviter_id = I.inviter_id)
  LEFT JOIN dbo.T_STF_SUBCONTRACTOR SC1 ON (SC1.subcontractor_id = D.subcontractor_id)
  LEFT JOIN dbo.T_STF_SUBCONTRACTOR SC2 ON (SC2.subcontractor_id = T.subcontractor_id)
  LEFT JOIN dbo.T_CUS_TSK_TASK_STATUS S ON (S.task_status_id=T.task_status_id)
  LEFT JOIN dbo.V_STF_SUB_LOCATION SL1 ON (SL1.sub_location_id=T.start_sub_location_id)
  LEFT JOIN dbo.V_STF_SUB_LOCATION SL2 ON (SL2.sub_location_id=T.end_sub_location_id)
  LEFT JOIN dbo.T_STF_CUSTOMER CU ON (CU.customer_id=T.customer_id)
  LEFT JOIN dbo.T_STF_CUSTOMER_SPLITTING_CODE SP ON (SP.splitting_id=T.splitting_id)
  LEFT JOIN dbo.V_CUS_TSK_CREDIT_FOR_TASK CR ON CR.task_id=T.task_id
  LEFT JOIN dbo.T_BKK_PROFORMA_INVOICE D1 ON (T.proforma_invoice_id=D1.proforma_invoice_id)
  LEFT JOIN dbo.T_BKK_TAX_INVOICE D2 ON (T.tax_invoice_id=D2.tax_invoice_id)
  LEFT JOIN dbo.T_BKK_INVOICE_RECEIPT D3 ON (T.invoice_receipt_id=D3.invoice_receipt_id)
  LEFT JOIN dbo.T_BKK_DELIVERY_NOTE D4 ON (T.delivery_note_id=D4.delivery_note_id)
  LEFT JOIN dbo.T_BKK_BILL_OF_LADING D5 ON (T.bill_of_lading_id=D5.bill_of_lading_id)
  LEFT JOIN dbo.V_CUS_TSK_CONTAINER CONTAINER1 ON (CONTAINER1.container_id=T.container1_id)
  LEFT JOIN dbo.V_CUS_TSK_CONTAINER CONTAINER2 ON (CONTAINER2.container_id=T.container2_id)
  LEFT JOIN dbo.V_STF_TRAILER TRAILER1 ON (TRAILER1.trailer_id=T.trailer1_id)
  LEFT JOIN dbo.V_STF_TRAILER TRAILER2 ON (TRAILER2.trailer_id=T.trailer2_id)
  LEFT JOIN dbo.T_STF_LUGGAGE_TYPE LUGGAGE_TYPE ON (LUGGAGE_TYPE.luggage_type_id=T.luggage_type_id)

One day the user asked the view for a query:

SELECT {many many columns}
FROM V_BIGGEST_VIEW_EVER
WHERE {column1}=1 AND
      {column2}=2 AND
      .......
      {and so and so}
      .......
      {columnN}=N

And the lazy biggest-view-ever worked and worked and after
5 minutes (!!) and not less it returns results.

Those tables had primary keys and foreign keys.

How can I reduce the time the query executes?
How can I reduce this view?

I searched on Google but I couldn't find anything that helped.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

离去的眼神 2024-10-14 06:39:35

让我们考虑一下该查询代表一个有效的业务需求。

仅仅因为视图很大并不意味着它应该表现得很差。从此视图中进行选择的性能主要由基础表的布局驱动。即使视图左连接超过 20 个查找表,SQL Server 也应该在几毫秒内返回结果,前提是表 T_CUS_TSK_TASK 已针对正在执行的查询正确建立索引。

您必须像任何其他查询优化一样处理此问题。调查主要 IO 因素 (SET STATISTICS IO ON),调查查询计划,查看基数估计,考虑统计信息是否正确,查看查询缺少索引提示并考虑如何才能相应地更改表架构。您的起点应该是这样的:设计索引。即使粗略地查看一下您的(帖子中未提供的)表架构,也应该会发现,如果 deleted 不是最左边的聚集索引键,那么您肯定遇到了问题。

您目前根据文本盲目地攻击查询的方法是完全不专业的。

现在当然很难相信这个查询代表了有效的业务需求。但是,尽管如此,您对查询优化和数据模型设计的看法(“那些表有主键和外键。”)用温和的术语来说是原始的。了解索引设计,了解覆盖索引,购买一本书(如下所示:Inside Microsoft SQL Server 2005:查询调整和优化)。

Lets consider for a minute that the query represents a valid business requirement.

Just because the view is big doesn't mean that it should perform badly. The performance of selecting from this view is driven primarily by the layout of the underlying tables. Even with a view that left joins over 20 lookup tables SQL Server should return the result in milliseconds, provided the table T_CUS_TSK_TASK is properly indexed for the query being performed.

You must approach this just as any other query optimization. Investigate what are the main IO factors (SET STATISTICS IO ON), investigate the query plan, look at the cardinality estimates, consider if statistics are correct, look at the query missing index hints and consider how can you change the table(s) schema accordingly. You starting point should be this: Designing Indexes. Even a cursory look at your (not provided in post) tables schema should reveal if, say, deleted is not the leftmost clustered index key then you certainly have a problem.

You current approach of blindly hacking at the query based on its text is completely unprofessional.

Now of course is hard to believe this query represents a valid business requirement. But, none the less, your view about query optimization and data model design ('Those tables had primary keys and foreign keys.') is primitive, to use a mild term. Read about index design, read about covering indexes, buy a book (like this: Inside Microsoft SQL Server 2005: Query Tuning and Optimization).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文