Bug #42948 MySQL Optimizer does not properly use Indexes on Views with "Group By"
| Submitted: | 17 Feb 2009 23:02 | Modified: | 3 Mar 2009 18:56 |
|---|---|---|---|
| Reporter: | John Kounis | Email Updates: | |
| Status: | Verified | Impact on me: | |
| Category: | MySQL Server: Optimizer | Severity: | S5 (Performance) |
| Version: | 5.0.67-0ubuntu6, 6.0.11 | OS: | Linux (Ubuntu 8.10) |
| Assigned to: | CPU Architecture: | Any | |
| Tags: | GROUP BY, Optimizer | ||
[17 Feb 2009 23:04]
John Kounis
Changed severity from S3 to S5 (Performance)
[28 Feb 2009 19:29]
Valeriy Kravchuk
Formally, this is not a bug. View is created as follows:
mysql> show create view qryTEST\G
*************************** 1. row ***************************
View: qrytest
Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `qrytest` AS select `tbltest`.`SubscriberID` AS `SubscriberID`,sum(`tbltest`.`Amount`) AS `Total` from `tbltest` group by `tbltest`.`SubscriberID`
character_set_client: latin1
collation_connection: latin1_swedish_ci
1 row in set (0,00 sec)
and as sum() is used server is forced to use emporary table to materialize the view, as explained at http://dev.mysql.com/doc/refman/5.1/en/view-algorithms.html:
mysql> EXPLAIN SELECT * FROM qryTEST WHERE SubscriberID=12345\G
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: <derived2>
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 402400
Extra: Using where
*************************** 2. row ***************************
id: 2
select_type: DERIVED
table: tbltest
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 524288
Extra: Using temporary; Using filesort
2 rows in set (20,09 sec)
It would be nice to remove this limitation one day and push condition down to the SELECT defining view, so this is a reasonable feature request.
[3 Mar 2009 18:56]
John Kounis
Thank you for the clarification. I read the link you provided and it's clear why this is happening. If it would affect the priority of the feature request, perhaps I could give a real-world example that I'm sure is common for database applications: I have many views to provide information about client transactions that use either aggregate functions or limit functions. A typical monthly invoice run looks something like this: SELECT CustomerID, <and a bunch of other stuff> FROM Customers INNER JOIN qryThisMonthsBalance ON Customer.ID = qryThisMonthsBalance.CustomerID INNER JOIN qryLastMonthsBalance ON Customer.ID = qryLastMonthsBalance.CustomerID INNER JOIN qryLastPayment on Customer.ID = qryLastPayment.CustomerID INNER JOIN qryLastInvoiceSent on Customer.ID = qryLastInvoiceSent.CustomerID ... and so on.... The performance of a query like the one above became unacceptable after converting from MSSQL to MySQL, since each of the views on which I was doing a join was doing a full table scan of 1.2 million records instead of using the "CustomerID" index. To restore normal performance, I had to write stored procedures to create temporary tables instead of using views as in the example above.
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.054 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.
Description: If I have a key on a field like SubscriberID and I perform a query such as : SELECT * FROM qryTEST WHERE SubscriberID=12345; then it is very fast, since it uses the "SubscriberID" key. However, if I create a view such as: CREATE VIEW qryTEST AS SELECT SubscriberID, SUM(Amount) as Total FROM tblTEST GROUP BY SubscriberID; then it does a table scan, which is very slow. How to repeat: Create a test table as follows: mysql> CREATE TABLE IF NOT EXISTS `tblTEST` ( -> `SubscriberID` int(11) NOT NULL, -> `TransactionID` int(11) NOT NULL, -> `Amount` decimal(19,4) NOT NULL, -> PRIMARY KEY (`TransactionID`), -> KEY (`SubscriberID`)); Query OK, 0 rows affected (0.03 sec) Insert a bunch of test data (I have a transaction table with over 1 million rows in it: mysql> mysql> INSERT INTO tblTEST -> SELECT SubscriberID, TransactionID, Amount -> FROM tblTransaction; Query OK, 1245064 rows affected (12.24 sec) Records: 1245064 Duplicates: 0 Warnings: 0 Create a view: mysql> mysql> CREATE VIEW qryTEST AS -> SELECT SubscriberID, SUM(Amount) as Total FROM tblTEST GROUP BY SubscriberID; Query OK, 0 rows affected (0.01 sec) Test the use of keys: mysql> mysql> EXPLAIN SELECT SUM(Amount) FROM tblTEST WHERE SubscriberID=12345; +----+-------------+---------+------+---------------+--------------+---------+-------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------+------+---------------+--------------+---------+-------+------+-------+ | 1 | SIMPLE | tblTEST | ref | SubscriberID | SubscriberID | 4 | const | 25 | | +----+-------------+---------+------+---------------+--------------+---------+-------+------+-------+ 1 row in set (0.00 sec) mysql> mysql> EXPLAIN SELECT * FROM qryTEST WHERE SubscriberID=12345; +----+-------------+------------+------+---------------+------+---------+------+---------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+------+---------------+------+---------+------+---------+---------------------------------+ | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 53228 | Using where | | 2 | DERIVED | tblTEST | ALL | NULL | NULL | NULL | NULL | 1245064 | Using temporary; Using filesort | +----+-------------+------------+------+---------------+------+---------+------+---------+---------------------------------+ 2 rows in set (1.52 sec)