-1

I've a complex SQL Statemant which needs per call (its for a calender view) 0.35sec. With 50 users and a 2 weeks of calender items, it takes 245sec which is much too long. I tried to optimize the query but at the moment I've no more idea.

I've an index on all related columns.

SELECT 
      DISTINCT tax.ta_id, tax.a_id, ax.status, ax.kunden_id, 
      IF(ax.todo_from != '0000-00-00', DATE_FORMAT(ax.todo_from, '%d.%m'), 'k. day_date') todo_from, 
      IF(ax.todo_until != '0000-00-00', DATE_FORMAT(ax.todo_until, '%d.%m'), 'k. day_date') todo_until, 
      IF((SELECT taj.city FROM suborders taj WHERE taj.a_id = tax.a_id AND taj.order_type = 'BRING' ORDER BY pos_id ASC LIMIT 1) != '', CONCAT(IF((SELECT short_name FROM locations WHERE company_id = '100' AND h_id = tax.h_id) != '', (SELECT short_name FROM locations WHERE company_id = '100' AND h_id = tax.h_id),tax.city),'>', CONCAT((SELECT IF((SELECT short_name FROM locations WHERE company_id = '100' AND h_id = taj.h_id) != '', (SELECT short_name FROM locations WHERE company_id = '100' AND h_id = taj.h_id), taj.city) FROM suborders taj WHERE taj.a_id = tax.a_id AND taj.order_type = 'BRING' AND taj.pos_id >= tax.pos_id ORDER BY pos_id ASC LIMIT 1))), IF((SELECT short_name FROM locations WHERE company_id = '100' AND h_id = tax.h_id) != '', (SELECT short_name FROM locations WHERE company_id = '100' AND h_id = tax.h_id),tax.city)) as city, 
  tax.user_id, tax.day_date, tax.pos_gesamt_id, '4' as class_type 
    FROM 
      suborders tax INNER JOIN orders ax ON (ax.a_id = tax.a_id) 
    WHERE 
      tax.order_type = 'TAKE' AND tax.user_id = '140' AND (tax.day_date = '2013-04-16' AND '2013-04-16' = (SELECT taj.day_date FROM suborders taj WHERE taj.a_id = tax.a_id AND taj.user_id = '140' AND taj.day_date = '2013-04-16' AND taj.user_id = '140' AND taj.order_type = 'BRING' ORDER BY pos_gesamt_id ASC)) AND tax.company_id = '100' GROUP BY tax.ta_id

Maybe you give me some recommendation.

4

1 に答える 1

1

書き直しの最初の試み(テーブルレイアウトがわからないため、テストされていません):-

SELECT DISTINCT tax.ta_id, tax.a_id, ax.status, ax.kunden_id, 
      IF(ax.todo_from != '0000-00-00', DATE_FORMAT(ax.todo_from, '%d.%m'), 'k. day_date') todo_from, 
      IF(ax.todo_until != '0000-00-00', DATE_FORMAT(ax.todo_until, '%d.%m'), 'k. day_date') todo_until, 
      IF((SELECT taj.city FROM suborders taj WHERE taj.a_id = tax.a_id AND taj.order_type = 'BRING' ORDER BY pos_id ASC LIMIT 1) != '', 
        CONCAT(
            IF(Sub2.short_name != '', Sub2.short_name,tax.city),
            '>', 
            CONCAT((
                SELECT IF(  Sub3.short_name != '', 
                            Sub3.short_name, 
                            taj.city) 
                FROM suborders taj 
                LEFT OUTER JOIN (SELECT h_id, short_name FROM locations WHERE company_id = '100') Sub3 ON Sub3.h_id = taj.h_id
                WHERE taj.a_id = tax.a_id 
                AND taj.order_type = 'BRING' 
                AND taj.pos_id >= tax.pos_id 
                ORDER BY pos_id 
                ASC LIMIT 1))), 
            IF(Sub2.short_name != '', Sub2.short_name, tax.city)) as city, 
  tax.user_id, tax.day_date, tax.pos_gesamt_id, '4' as class_type 
FROM suborders tax 
INNER JOIN orders ax ON (ax.a_id = tax.a_id) 
INNER JOIN (
    SELECT DISTINCT a_id 
    FROM suborders taj 
    WHERE taj.user_id = '140' 
    AND taj.day_date = '2013-04-16' 
    AND taj.user_id = '140' 
    AND taj.order_type = 'BRING' 
) Sub4 ON Sub4.a_id = tax.a_id 
LEFT OUTER JOIN (SELECT h_id, short_name FROM locations WHERE company_id = '100') Sub2 ON Sub2.h_id = tax.h_id
 WHERE tax.order_type = 'TAKE' 
 AND tax.user_id = '140' 
 AND tax.day_date = '2013-04-16' 
 AND tax.company_id = '100' 
 GROUP BY tax.ta_id

この段階では、物事がどのように適合するかを本当に混乱させているため、これ以上先に進むことができるかどうかはわかりません.

問題は、多数の相関サブクエリがあり、これらが遅いことです (つまり、クエリの外部からのフィールドに依存するサブクエリ - したがって、MySQL はすべての行に対してそのサブクエリを実行する必要があります)。私は解決できるこれらのいくつかを削除し、それらをサブクエリへの結合に置き換えました(これらにより、MySQLはサブクエリを1回実行してから、結果をメインクエリに結合できます)

しかし、クエリ内でサブクエリを関連付けたり、異なるテーブルやサブクエリ間でエイリアス名を再利用したりすると、非常に混乱します。

クエリの意図を理解できれば、クエリのパフォーマンスを大幅に向上させることができます。

さらに、集計列を使用せずにメインクエリで GROUP BY を使用しました。これは DISTINCT の代わりに行われることもありますが、DISTINCT もあります。

于 2013-04-17T16:53:41.997 に答える