我具有以下功能:
DELIMITER $$
DROP FUNCTION IF EXISTS f_prevpricedate;
CREATE FUNCTION f_prevpricedate (id CHAR(8), startdate DATE)
RETURNS DATE
BEGIN
DECLARE prevpricedate DATE;
SELECT MAX(f.p_date) INTO prevpricedate
FROM fp_v2_fp_basic_prices AS f
WHERE f.fsym_id = id AND f.p_date<startdate;
RETURN prevpricedate;
END$$
基本上,这只是返回最接近输入日期的日期(以前的日期)。但是,由于表非常大,因此运行非常慢。
任何人都知道如何优化它吗?
答案 0 :(得分:1)
首先,检查explain select ...
的内容。
fp_v2_fp_basic_prices.fsym_id
和fp_v2_fp_basic_prices.p_date
被索引了吗?索引使数据库可以快速匹配和比较行,而不必查看所有行。如果没有索引,则必须比较表中的每一行。
例如...
mysql> select count(*) from foo;
+----------+
| count(*) |
+----------+
| 3 |
+----------+
mysql> explain select max(this) from foo where this < 42;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | foo | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
这表明查询正在进行全表扫描。它不使用键(索引),查询的类型为ALL
,并且认为它必须查看表中的所有3行。
mysql> alter table foo add index foo_this (this);
Query OK, 0 rows affected (0.07 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> explain select max(this) from foo where this < 42;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Select tables optimized away |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
这是在添加索引之后。 Select tables optimized away
告诉我们优化器已经知道可以使用索引来优化整个查询。
在您的情况下,您要按fsym_id
和p_date
两列进行搜索。 MySQL在查询中每个表只使用一个索引。因此,即使您在fsym_id
上有一个索引,在p_date
上有一个索引,它也只会使用一个。为了使此查询的性能很好,您需要在单个索引中同时使用它们。
alter table fp_v2_fp_basic_prices add index(p_date, fsym_id);
这将适用于仅使用p_date
的查询以及同时使用p_date
和fsym_id
的查询。因此,您不需要仅p_date
上的索引。但这并不涵盖仅使用fsym_id
的查询。有关更多详细信息,请参见this answer。
另请参阅: