mysql:在这种情况下,索引多线程的最佳方法是什么
我有下面的sql命令,这需要很多时间。我在考虑索引mysql:在这种情况下,索引多线程的最佳方法是什么,mysql,indexing,query-optimization,Mysql,Indexing,Query Optimization,我有下面的sql命令,这需要很多时间。我在考虑索引 SELECT `daily_price_history`.`high`, `daily_price_history`.`low`, `daily_price_history`.`open`, `daily_price_history`.`datetime`, `daily_price_history`.`close`, `daily_price_history`.`creat
SELECT `daily_price_history`.`high`,
`daily_price_history`.`low`,
`daily_price_history`.`open`,
`daily_price_history`.`datetime`,
`daily_price_history`.`close`,
`daily_price_history`.`creation_time`
FROM `daily_price_history`
WHERE (`daily_price_history`.`datetime_utc` BETWEEN '2015-12-04 18:43:28.710229' AND '2020-12-02 18:43:28.710229'
AND `daily_price_history`.`symbol` = 'A')
ORDER BY `daily_price_history`.`creation_time` ASC
因此,索引多个列(datetime\u utc,symbol)
是索引两个独立列的最佳方法
我的显示创建表
CREATE TABLE `daily_price_history` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`symbol` varchar(50) NOT NULL,
`symbolExpectionCount` int(11) NOT NULL,
`url` longtext NOT NULL,
`volume` double NOT NULL,
`high` double NOT NULL,
`low` double NOT NULL,
`open` double NOT NULL,
`datetime` bigint(20) NOT NULL,
`datetime_utc` datetime(6) NOT NULL,
`close` double NOT NULL,
`creation_time` datetime(6) NOT NULL,
`lot_time` datetime(6) NOT NULL,
`periodType` varchar(50) NOT NULL,
`symbolId_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `daily_price_history_symbolId_id_30077f62_fk_symbol_list_id` (`symbolId_id`),
KEY `datetime` (`datetime`),
CONSTRAINT `daily_price_history_symbolId_id_30077f62_fk_symbol_list_id` FOREIGN KEY (`symbolId_id`) REFERENCES `symbol_list` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11549349 DEFAULT CHARSET=utf8mb4
我有一个名为
symbol\u list
的表,因此这里symbol
只是symbol的文本,而symbol\u id
是与symbol\u list
的外键关系,在大多数情况下,MySQL只会对每个表引用使用一个索引。因此,创建两个单独的索引并不是最好的策略
最好在(symbol,datetime\u utc)
上设置索引。索引中列的顺序很重要
您的查询对symbol
有一个相等条件,因此它应该先执行
datetime\u utc
的范围条件使其最好放在第二位
您不能同时针对范围条件和订货条件进行优化。您必须选择其中一个进行优化
因此,该指数应为:
-对两个搜索词进行优化,但这需要对结果进行文件排序(symbol,datetime\u utc)
-通过优化订单,避免文件排序,但不会针对日期时间utc条件进行优化(符号,创建时间)
您可能想查看我的演示文稿,或者。您需要一个
主键。它必须是独一无二的。如果您可以保证(symbol,datetime\u utc)
始终是唯一的,那么这是最佳选择:
PRIMARY KEY (symbol, datetime_utc)
如果你不能保证唯一性,那就做吧
id INT UNSIGNED AUTO_INCREMENT NOT NULL,
PRIMARY KEY (symbol, datetime_utc, id),
INDEX(id)
(如果最终可能有超过40亿行,请将INT
更改为BIGINT
。)
这令人费解:
WHERE datetime_utc ...
ORDER BY creation_time
这会更快,并且通常会为我们提供相同的结果(甚至更好的结果),这两个方面都是相同的列:
WHERE datetime_utc ...
ORDER BY datetime_utc
如果您希望有数十亿行,那么应该尽可能地缩减每个数据类型
- 您是否也有
卷
列?有些索引不适合INT
- 规范化
符号
,并将其替换为SMALLINT UNSIGNED
(2个字节,最多64K值)或类似内容
open
等的值不适合BRK.A的某些较小数据类型
- 低价股可能需要超过2位小数
- 以前的读数是分数,分母是2的幂
- 警告:上述建议基于美国市场;其他市场可能会有更多问题
名称daily\u price\u history
表示每天每个符号一行?然而,使用8字节的DATETIME(6)
意味着你正在记录每一笔交易。(DATE
仅为3个字节。)
进行一些更改后,请提供SHOW CREATE TABLE
、主要查询和我的问题的答案。我可能会有更多的建议。我只想按日期时间编制索引并尝试一下。索引的类型应该是btree或任何其他允许选择范围的索引类型。关于符号我的意见是,包含符号不会有太多好处:一旦选择了日期时间范围内的行,可以在内存中快速执行进一步的筛选。您可以尝试这两种选择。@Tarik-这个场景是一个很好的例子,说明INDEX(symbol,dt)
将显著优于INDEX(dt)
或INDEX(symbol)
。我们看到where(daily_price_history.datetime_utc介于'2015-12-04 18:43:28.710229'和'2020-12-02 18:43:28.710229'之间,daily_history.symbol='A')
。因此顺序是datetime_utc
,然后是symbol
。所以mysql不会忽略索引(symbol,datetime_utc)
你提到的你的查询对symbol有一个相等的条件,所以应该先进行查询。
我没有意识到这一点,所以原因可能是这样的。不,MySQL的优化器被设计为知道和是相等的。换句话说,A和B
给出与B和A
相同的结果。因此,不管你写的顺序如何在您的查询中,MySQL可以使用适当的索引。我使用的是TD america数据。我有重复的数据。因为有时我会错误地获取两次数据,所以我使用creation\u time
和datetime。因此,对于一个符号,可以有多个相同的datetime。我将使用creation\u time
。数据最终也会增长。@SanthoshYedidi-将插入
更改为在重复密钥更新时插入…
,以便自动“更新”当有dup时。也许你可以摆脱创建时间
。但是,我每天必须获得10000个符号的数据,如果使用插入
进行更新,这需要很多时间。目前我使用批插入,因此需要2.5小时。因为td america不允许每秒超过2个请求,即使他们说每秒120个请求sec@SanthoshYedidi-我不理解这个问题。需要时间的是数据收集,而不是INSERT
或IODKU语句。一批INSERT
1000行只需要几秒钟。但从td amarica获取这1000行需要500秒。或者是一个“请求”不止一个符号?@Tarik-对一个复合索引来说是的。symbol
必须是性能的第一位。但随后我介绍了一个案例,其中多个索引会更好。