web-dev-qa-db-ja.com

Mysql:サブクエリの最適化を伴う大規模なクエリ

家の中にクエリ最適化の達人はいますか?

とにかく、私はこれを2つの面に取り付けようとしています。1つはそれを回避する方法をコーディングしようとしていますが、2つ目は、より複雑で堅牢な修正を作成する際に、実際の最適化が短いトレムに役立つと考えています。したがって、これ以上の説明なしで、ここにクエリがあります:

select 
      Date(events.start_time) as event_date, 
      if(transactions.type = 'BoxOfficeTransaction', 
         (select sales_outlets.name 
            from 
                  ticket_agents, 
                  sales_outlets 
            where 
                  transactions.ticket_agent_id = ticket_agents.id 
              and ticket_agents.sales_outlet_id = sales_outlets.id), 
         transactions.type) as location, 
      ticket_types.name as price_type, 
      ticket_types.price as cost, 
      if (transactions.type = 'WebTransaction', 
          ( select count(tickets.id) 
               from 
                  tickets, 
                  transactions, 
                  events, 
                  ticket_types 
               where 
                      tickets.transaction_id = transactions.id 
                  and tickets.event_id = events.id 
                  and tickets.ticket_type_id = ticket_types.id 
                  and transactions.type = 'WebTransaction' 
                  and ticket_types.name = price_type 
                  and Date(events.start_time) = event_date 
                  and tickets.status = 'active'), 
          ( select count(tickets.id) 
               from 
                  tickets, 
                  transactions, 
                  events, 
                  ticket_types, 
                  ticket_agents, 
                  sales_outlets 
               where 
                      tickets.transaction_id = transactions.id 
                  and tickets.event_id = events.id 
                  and tickets.ticket_type_id = ticket_types.id 
                  and transactions.ticket_agent_id = ticket_agents.id 
                  and ticket_agents.sales_outlet_id = sales_outlets.id 
                  and ticket_types.name = price_type 
                  and Date(events.start_time) = event_date 
                  and tickets.status = 'active' 
                  and sales_outlets.name = location) 
         ) as quantity, 
      ( select quantity * ticket_types.price) as value, 
      ( select tickets.purchase_price * quantity) as revenue 
   from 
      events, 
      transactions, 
      tickets, 
      ticket_types 
   where 
          transactions.event_id = events.id 
      and tickets.transaction_id = transactions.id 
      and tickets.ticket_type_id = ticket_types.id 
      and events.start_time >= '2012-11-15 05:00:00' 
      and events.start_time <= '2013-01-06 04:59:59' 
   group by 
      event_date, 
      location, 
      ticket_types.name

私が知っているやっかいな。説明は次のとおりです。

+----+--------------------+---------------+--------+-------------------------------------+-------------------+---------+---------------------------------------+------+-----------------------------------------------------------+
| id | select_type        | table         | type   | possible_keys                       | key               | key_len | ref                                   | rows | Extra                                                     |
+----+--------------------+---------------+--------+-------------------------------------+-------------------+---------+---------------------------------------+------+-----------------------------------------------------------+
|  1 | PRIMARY            | events        | index  | PRIMARY,event_date                  | event_date        | 13      | NULL                                  |   53 | Using where; Using index; Using temporary; Using filesort |
|  1 | PRIMARY            | transactions  | ref    | PRIMARY,event_id                    | event_id          | 5       | abg_dev.events.id                     |   23 | Using where                                               |
|  1 | PRIMARY            | tickets       | ref    | trans_id,ticket_types_id            | trans_id          | 5       | abg_dev.transactions.id               |    2 | Using where                                               |
|  1 | PRIMARY            | ticket_types  | eq_ref | PRIMARY                             | PRIMARY           | 4       | abg_dev.tickets.ticket_type_id        |    1 |                                                           |
|  4 | DEPENDENT SUBQUERY | sales_outlets | ref    | PRIMARY,sales_outlet_name           | sales_outlet_name | 767     | func                                  |    1 | Using where; Using index                                  |
|  4 | DEPENDENT SUBQUERY | ticket_types  | ref    | PRIMARY,type_name,ticket_types_name | type_name         | 767     | func                                  |    4 | Using index                                               |
|  4 | DEPENDENT SUBQUERY | tickets       | ref    | trans_id,ticket_types_id            | ticket_types_id   | 5       | abg_dev.ticket_types.id               |  441 | Using where                                               |
|  4 | DEPENDENT SUBQUERY | events        | eq_ref | PRIMARY                             | PRIMARY           | 4       | abg_dev.tickets.event_id              |    1 | Using where                                               |
|  4 | DEPENDENT SUBQUERY | transactions  | eq_ref | PRIMARY,ticket_agent_id             | PRIMARY           | 4       | abg_dev.tickets.transaction_id        |    1 |                                                           |
|  4 | DEPENDENT SUBQUERY | ticket_agents | eq_ref | PRIMARY                             | PRIMARY           | 4       | abg_dev.transactions.ticket_agent_id  |    1 | Using where                                               |
|  3 | DEPENDENT SUBQUERY | ticket_types  | ref    | PRIMARY,type_name,ticket_types_name | type_name         | 767     | func                                  |    4 | Using index                                               |
|  3 | DEPENDENT SUBQUERY | tickets       | ref    | trans_id,ticket_types_id            | ticket_types_id   | 5       | abg_dev.ticket_types.id               |  441 | Using where                                               |
|  3 | DEPENDENT SUBQUERY | transactions  | eq_ref | PRIMARY                             | PRIMARY           | 4       | abg_dev.tickets.transaction_id        |    1 | Using where                                               |
|  3 | DEPENDENT SUBQUERY | events        | eq_ref | PRIMARY                             | PRIMARY           | 4       | abg_dev.tickets.event_id              |    1 | Using where                                               |
|  2 | DEPENDENT SUBQUERY | ticket_agents | eq_ref | PRIMARY                             | PRIMARY           | 4       | transactions.ticket_agent_id          |    1 |                                                           |
|  2 | DEPENDENT SUBQUERY | sales_outlets | eq_ref | PRIMARY                             | PRIMARY           | 4       | abg_dev.ticket_agents.sales_outlet_id |    1 |                                                           |
+----+--------------------+---------------+--------+-------------------------------------  +-------------------+---------+---------------------------------------+------+-----------------------------------------------------------+
16 rows in set, 2 warnings (0.00 sec) 

インデックス:

mysql> show indexes from events;
+--------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table  | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| events |          0 | PRIMARY    |            1 | id          | A         |          53 |     NULL | NULL   |      | BTREE      |         |               |
| events |          1 | event_date |            1 | start_time  | A         |          53 |     NULL | NULL   | YES  | BTREE      |         |               |
| events |          1 | event_date |            2 | id          | A         |          53 |     NULL | NULL   |      | BTREE      |         |               |
+--------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)

mysql> show indexes from transactions;
+--------------+------------+---------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table        | Non_unique | Key_name            | Seq_in_index | Column_name         | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------------+------------+---------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| transactions |          0 | PRIMARY             |            1 | id                  | A         |        1274 |     NULL | NULL   |      | BTREE      |         |               |
| transactions |          1 | ticket_agent_id     |            1 | ticket_agent_id     | A         |          41 |     NULL | NULL   | YES  | BTREE      |         |               |
| transactions |          1 | ticket_agent_id     |            2 | id                  | A         |        1274 |     NULL | NULL   |      | BTREE      |         |               |
| transactions |          1 | user_id             |            1 | user_id             | A         |        1274 |     NULL | NULL   |      | BTREE      |         |               |
| transactions |          1 | user_id             |            2 | id                  | A         |        1274 |     NULL | NULL   |      | BTREE      |         |               |
| transactions |          1 | payment_method_type |            1 | payment_method_type | A         |           5 |     NULL | NULL   |      | BTREE      |         |               |
| transactions |          1 | payment_method_type |            2 | id                  | A         |        1274 |     NULL | NULL   |      | BTREE      |         |               |
| transactions |          1 | created_at          |            1 | created_at          | A         |        1274 |     NULL | NULL   |      | BTREE      |         |               |
| transactions |          1 | created_at          |            2 | id                  | A         |        1274 |     NULL | NULL   |      | BTREE      |         |               |
| transactions |          1 | created_at_by_user  |            1 | created_at          | A         |        1274 |     NULL | NULL   |      | BTREE      |         |               |
| transactions |          1 | created_at_by_user  |            2 | user_id             | A         |        1274 |     NULL | NULL   |      | BTREE      |         |               |
| transactions |          1 | event_id            |            1 | event_id            | A         |          55 |     NULL | NULL   | YES  | BTREE      |         |               |
| transactions |          1 | event_id            |            2 | id                  | A         |        1274 |     NULL | NULL   |      | BTREE      |         |               |
+--------------+------------+---------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
13 rows in set (0.00 sec)

mysql> show indexes from tickets;
+---------+------------+-----------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table   | Non_unique | Key_name        | Seq_in_index | Column_name    | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+-----------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tickets |          0 | PRIMARY         |            1 | id             | A         |        4330 |     NULL | NULL   |      | BTREE      |         |               |
| tickets |          0 | barcode_index   |            1 | barcode        | A         |        4330 |     NULL | NULL   | YES  | BTREE      |         |               |
| tickets |          1 | trans_id        |            1 | transaction_id | A         |        2165 |     NULL | NULL   | YES  | BTREE      |         |               |
| tickets |          1 | trans_id        |            2 | id             | A         |        4330 |     NULL | NULL   |      | BTREE      |         |               |
| tickets |          1 | ticket_types_id |            1 | ticket_type_id | A         |           9 |     NULL | NULL   | YES  | BTREE      |         |               |
| tickets |          1 | ticket_types_id |            2 | id             | A         |        4330 |     NULL | NULL   |      | BTREE      |         |               |
+---------+------------+-----------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
6 rows in set (0.00 sec)

mysql> show indexes from sales_outlets;
+---------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table         | Non_unique | Key_name          | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| sales_outlets |          0 | PRIMARY           |            1 | id          | A         |           2 |     NULL | NULL   |      | BTREE      |         |               |
| sales_outlets |          1 | sales_outlet_name |            1 | name        | A         |           2 |     NULL | NULL   |      | BTREE      |         |               |
| sales_outlets |          1 | sales_outlet_name |            2 | id          | A         |           2 |     NULL | NULL   |      | BTREE      |         |               |
+---------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)

mysql> show indexes from ticket_types;
+--------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table        | Non_unique | Key_name          | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| ticket_types |          0 | PRIMARY           |            1 | id          | A         |           2 |     NULL | NULL   |      | BTREE      |         |               |
| ticket_types |          1 | type_name         |            1 | name        | A         |           2 |     NULL | NULL   |      | BTREE      |         |               |
| ticket_types |          1 | type_name         |            2 | id          | A         |           2 |     NULL | NULL   |      | BTREE      |         |               |
| ticket_types |          1 | price             |            1 | price       | A         |           2 |     NULL | NULL   |      | BTREE      |         |               |
| ticket_types |          1 | price             |            2 | id          | A         |           2 |     NULL | NULL   |      | BTREE      |         |               |
| ticket_types |          1 | ticket_types_name |            1 | name        | A         |           2 |     NULL | NULL   |      | BTREE      |         |               |
| ticket_types |          1 | ticket_types_name |            2 | id          | A         |           2 |     NULL | NULL   |      | BTREE      |         |               |
+--------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
7 rows in set (0.00 sec)

トランザクションは約3000行チケットは約6000行セールスアウトレットは3行Ticket_typesは18行

ありがとう!

1
Ross R

頭が痛くなりましたが、少し...各イベントIDは、映画(表示されます)などの特定の日時であるようです。1つのイベントはX日目の2:30の映画で、別のイベントはX日目の映画@ 4:45。Y日@ 2:30の同じ映画は別のIDになります...とはいえ、興行収入とWebベースのトランザクションのカウントを分類しようとしています。興行収入の場合は、販売店の場所の名前で特定の場所を追跡します。それ以外の場合は、「WebTransaction」の説明を使用します。誰でも映画のチケットを購入して、関連する劇場に適用できるためです。繰り返しますが、データコンテキストの推測に基づいています。

そうは言っても、イベントIDごとに特定の場所ごとにすべてのチケットを事前にクエリするだけです...「PreQuery」であるチケットごとのカウント、コスト基準などを取得しますが、date_startに乗ります。

ここで、OUTERクエリを使用してロールアップし、イベントの日付と場所でグループ化し、個々のID(イベント)ごとのチケットの合計、収益、値をSUMming()し、特定のDAYでグループ化します。

適用する実際のデータがないため、微調整を少し調整することができます...

SELECT STRAIGHT_JOIN
      DATE( PreQuery.Start_Time ),
      PreQuery.Location,
      PreQuery.Price_Type,
      PreQuery.Cost,
      SUM( PreQuery.NumberOfTicketIDs ) as NumTicketsForDay,
      SUM( PreQuery.Value ) as TicketValueForDay,
      SUM( PreQuery.Revenue ) as TicketRevenueForDay
   from
      ( select
              EV.ID as WebEventID,
              EV.Start_Time,
              TR.Type
              IF( TR.Type = 'BoxOfficeTransaction', SO.name, TR.Type ) as Location,
              TT.Name as Price_Type,
              TT.Price as Cost,
              count(TICK.id) NumberOfTicketIDs,
              SUM( TICK.Quantity * TT.Price ) as Value,
              SUM( TICK.Purchase_Price * TICK.Quantity ) as Revenue
           from 
              events EV

                 JOIN tickets TICK
                    ON EV.ID = TICK.Event_ID
                   AND TICK.Status = 'active'

                    JOIN transactions TR
                       ON TICK.Transaction_ID = TR.ID

                       LEFT JOIN ticket_agents TA
                          ON TR.Ticket_Agent_ID = TA.ID
                          LEFT JOIN Sales_Outlets SO
                             ON TA.Sales_Outlet_ID = SO.ID
                    JOIN ticket_types TT
                       ON TICK.Ticket_Type_ID = TT.ID
           where
                  EV.start_time >= '2012-11-15 05:00:00' 
              and EV.start_time <= '2013-01-06 04:59:59' 
           group by 
              EV.ID,
              TR.Type
              IF( TR.Type = 'BoxOfficeTransaction', SO.name, TR.Type ) ) as PreQuery
   group by
      DATE( PreQuery.Start_Time ),
      PreQuery.Location,
      PreQuery.Price_Type,
      PreQuery.Cost
4
DRapp

より良いアイデアを持つために:

  • このクエリの実行方法、
  • どのテーブルに対してどのくらいのテーブルIOが実行されるか、

この回答で使用されている手法を使用できます。

https://stackoverflow.com/questions/11160522/why-does-mysqls-performance-decrease-when-queries-are-executed-in-parallel/11341343#1134134

そして、performance_schema、テーブル、またはインデックスによって収集された統計を確認します。

0
Marc Alff