gpt4 book ai didi

MySQL优化存储过程中慢UNION查询

转载 作者:行者123 更新时间:2023-11-29 11:28:23 25 4
gpt4 key购买 nike

我的存储过程中有以下代码,它基本上将 SQL 文本连接到 while 循环中的一个大查询中,然后执行它。我有来自 7 个不同表的 7 个 UNION ALL 语句,其中包含一些输入参数(table_name1...7start_date结束日期):

BEGIN

DECLARE v_max INT UNSIGNED DEFAULT 58;
DECLARE v_counter INT UNSIGNED DEFAULT 1;
SET @sql_text = '';
WHILE v_counter < v_max DO
-- Build SQL string
SET @sql_text = CONCAT(@sql_text,
CONCAT(' SELECT
(SELECT i.name FROM instrument i WHERE i.id =',v_counter,' LIMIT 1) AS Instrument,
(SELECT AVG(p.ask-p.bid) AS avg_spread
FROM ',table_name1,' p
WHERE p.instrument_id=',v_counter,' AND FROM_UNIXTIME(p.system_datetime/1000000) BETWEEN \'',start_date,'\' AND \'',end_date,'\') AS One

,

(SELECT AVG(p.ask-p.bid) AS avg_spread
FROM ', table_name2,' p
WHERE p.instrument_id=',v_counter,' AND FROM_UNIXTIME(p.system_datetime/1000000) BETWEEN \'',start_date,'\' AND \'', end_date,'\') AS Two

,

(SELECT AVG(p.ask-p.bid) AS avg_spread
FROM ',table_name3,' p
WHERE p.instrument_id=',v_counter,' AND FROM_UNIXTIME(p.system_datetime/1000000) BETWEEN \'', start_date,'\' AND \'',end_date,'\') AS Three

/* ... more unions here ...*/
,

(SELECT AVG(p.ask-p.bid) AS avg_spread
FROM ',table_name7,' p
WHERE p.instrument_id=',v_counter,' AND FROM_UNIXTIME(p.system_datetime/1000000) BETWEEN \'', start_date,'\' AND \'',end_date,'\') AS Seven UNION ALL ')

);


SET v_counter=v_counter+1;

END WHILE;

-- Remove extra UNION ALL from SQL string
SET @sql_text = LEFT(@sql_text,LENGTH(@sql_text) - LENGTH(' UNION ALL'));
-- SELECT LEFT(@sql_text,LENGTH(@sql_text) - LENGTH(' UNION ALL'));

-- Prepare and execute statement
PREPARE stmt3 FROM @sql_text;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
END

请问有什么办法可以优化这个查询(七个表平均每个表有350万条记录),执行时间在6到25分钟之间?表是 MyISAM,相同,以下是它们的结构:

CREATE TABLE `prices_all_2016_06_13_5` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`instrument_id` TINYINT(4) NOT NULL,
`ask` DECIMAL(12,6) NOT NULL,
`bid` DECIMAL(12,6) NOT NULL,
`system_datetime` DECIMAL(20,0) NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `Index 3` (`instrument_id`) USING HASH,
INDEX `Index 4` (`system_datetime`)
)
COLLATE='utf8_unicode_ci'
ENGINE=MyISAM
ROW_FORMAT=COMPACT
AUTO_INCREMENT=3882184
;

编辑:这是解释:

"id"    "select_type"   "table" "type"  "possible_keys" "key"   "key_len"   "ref"   "rows"  "Extra"
"1" "PRIMARY" \N \N \N \N \N \N \N "No tables used"
"9" "SUBQUERY" \N \N \N \N \N \N \N "Impossible WHERE noticed after reading const tables"
"8" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "64566" "Using where"
"7" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "71061" "Using where"
"6" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "43979" "Using where"
"5" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "69852" "Using where"
"4" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "117355" "Using where"
"3" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "70672" "Using where"
"2" "SUBQUERY" "i" "const" "PRIMARY" "PRIMARY" "4" "const" "1" \N
"10" "UNION" \N \N \N \N \N \N \N "No tables used"
"18" "SUBQUERY" \N \N \N \N \N \N \N "Impossible WHERE noticed after reading const tables"
"17" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "52505" "Using where"
"16" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "68781" "Using where"
"15" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "40055" "Using where"
"14" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "32054" "Using where"
"13" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "57465" "Using where"
"12" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "33265" "Using where"
"11" "SUBQUERY" "i" "const" "PRIMARY" "PRIMARY" "4" "const" "1" \N
"19" "UNION" \N \N \N \N \N \N \N "No tables used"
"27" "SUBQUERY" \N \N \N \N \N \N \N "Impossible WHERE noticed after reading const tables"
"26" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "75411" "Using where"
"25" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "91574" "Using where"
"24" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "47560" "Using where"
"23" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "80731" "Using where"
"22" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "139225" "Using where"
"21" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "109131" "Using where"
"20" "SUBQUERY" "i" "const" "PRIMARY" "PRIMARY" "4" "const" "1" \N
"28" "UNION" \N \N \N \N \N \N \N "No tables used"
"36" "SUBQUERY" \N \N \N \N \N \N \N "Impossible WHERE noticed after reading const tables"
"35" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "67288" "Using where"
"34" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "83522" "Using where"
"33" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "46650" "Using where"
"32" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "50401" "Using where"
"31" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "73280" "Using where"
"30" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "50836" "Using where"
"29" "SUBQUERY" "i" "const" "PRIMARY" "PRIMARY" "4" "const" "1" \N
"37" "UNION" \N \N \N \N \N \N \N "No tables used"
"45" "SUBQUERY" \N \N \N \N \N \N \N "Impossible WHERE noticed after reading const tables"
"44" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "59256" "Using where"
"43" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "54092" "Using where"
"42" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "41561" "Using where"
"41" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "51928" "Using where"
"40" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "64368" "Using where"
"39" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "60471" "Using where"
"38" "SUBQUERY" "i" "const" "PRIMARY" "PRIMARY" "4" "const" "1" \N
"46" "UNION" \N \N \N \N \N \N \N "No tables used"
"54" "SUBQUERY" \N \N \N \N \N \N \N "Impossible WHERE noticed after reading const tables"
"53" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "59213" "Using where"
"52" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "56071" "Using where"
"51" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "47653" "Using where"
"50" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "46033" "Using where"
"49" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "56180" "Using where"
"48" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "47262" "Using where"
"47" "SUBQUERY" "i" "const" "PRIMARY" "PRIMARY" "4" "const" "1" \N
"55" "UNION" \N \N \N \N \N \N \N "No tables used"
"63" "SUBQUERY" \N \N \N \N \N \N \N "Impossible WHERE noticed after reading const tables"
"62" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "69552" "Using where"
"61" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "100487" "Using where"
"60" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "78156" "Using where"
"59" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "105721" "Using where"
"58" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "128156" "Using where"
"57" "SUBQUERY" "p" "ref" "Index 3" "Index 3" "1" "const" "114533" "Using where"
"56" "SUBQUERY" "i" "const" "PRIMARY" "PRIMARY" "4" "const" "1" ...

最佳答案

FROM_UNIXTIME(p.system_datetime/1000000)
BETWEEN \'', start_date,'\' AND \'', end_date,'\'

不要隐藏函数中的列;不能使用索引。相反:

p.system_datetime
BETWEEN 1000000*UNIX_TIMESTAMP(\'', start_date,'\')
AND 1000000*UNIX_TIMESTAMP(\'', end_date,'\')

使用 DECIMAL(20,0) 而不是 DECIMAL(20,6) 从而避免 1000000 的原因是什么?另请注意,新的 MySQL 具有 DATETIME(6)TIMESTAMP(6),可为您提供所需的微秒分辨率。

重新编写查询后,p 将需要它来提高效率:

INDEX(instrument_id, system_datetime)

此外,如果这些表具有相同的结构,那么可能最好有一个表,而不是很多。它可能需要一个额外的列来区分每行属于哪个“表”。您似乎正在执行“通过表名称分区”(prices_all_2016_06_13_5 等)。

此外,切换到 InnoDB,并设计“正确的”主键(可能是“复合”),将因“集群”而给您带来另一次性能提升。

分区可能值得也可能不值得。 (它通常买不到性能。)

我需要更好地了解您的疑问,以便提供进一步建议。

关于MySQL优化存储过程中慢UNION查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37832391/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com