mysql:在这种情况下,索引多线程的最佳方法是什么

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

我有下面的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`.`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
必须是性能的第一位。但随后我介绍了一个案例,其中多个索引会更好。