也许你可以帮助我。我需要查询3个表以获取金融股的数据。
我们的想法是转到工具表,查找每种工具的指数,然后将该特定工具的所有价格与单独表格中的指标一起使用。
表stockdata
和indicators
几乎都是50.000条记录。 instruments
只有30岁。
这是无效的查询:
SELECT
indicators.ddate,
instruments.name,
indicators.sma_14,
indicators.sma_5,
stockdata.close
FROM
indicators
INNER JOIN instruments ON (indicators.instrument_id=instruments.id)
INNER JOIN stockdata ON (instruments.name=stockdata.name)
这是EXPLAIN结果
+----+-------------+-------------+-------+-----------------------------+---------------------+---------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | rows | Extra |
+----+-------------+-------------+-------+-----------------------------+---------------------+---------+------+-------------+
| 1 | SIMPLE | instruments | index | PRIMARY,instruments_index01 | instruments_index01 | 61 | 25 | Using index |
| 1 | SIMPLE | indicators | ref | indicators_index01 | indicators_index01 | 5 | 973 | Using where |
| 1 | SIMPLE | stockdata | ref | stockdata_index01 | stockdata_index01 | 31 | 1499 | Using where |
+----+-------------+-------------+-------+-----------------------------+---------------------+---------+------+-------------+
我非常感谢您提供的任何帮助!
这是我的问题中涉及的部分表的架构:
TABLE `indicators` (
`id` int AUTO_INCREMENT NOT NULL,<br>
`instrument_id` int,
`date` date,
`sma_5` float(10,3),
`sma_14` float(10,3),
`ema_14` float(10,3),
/* Keys */
PRIMARY KEY (`id`)
)
TABLE `instruments` (
`id` int AUTO_INCREMENT NOT NULL,
`name` char(20),
`country` char(50),
`newsquery` char(100),
/* Keys */
PRIMARY KEY (`id`)
)
TABLE `stockdata` (
`id` int AUTO_INCREMENT NOT NULL,
`name` char(10),
`date` date,
`open` float,
`high` float,
`low` float,
`close` float,
`volume` int,
`adjclose` float,
/* Keys */
PRIMARY KEY (`id`)
)
答案 0 :(得分:5)
您正在将indicators
表加入instruments
表,并且indicators.instrument_id
列未编入索引。
您还使用instruments
和stockdata
列将instruments.name
表加入stockdata.name
表,这两列都是CHAR
类型。使用CHAR
或VARCHAR
加入通常比使用INT
列加入要慢得多:
Using CHAR keys for joins, how much is the overhead?
更糟糕的是,您的CHAR
列的大小不同(分别为char(20)
和char(10)
),并且未对其编制索引。这真的让MySQL变得困难!有关详细信息,请参阅How MySQL Uses Indexes。
理想情况下,您应该更改表结构,以便可以使用索引INT
字段执行连接。像这样:
CREATE TABLE `instruments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(20) DEFAULT NULL,
`country` char(50) DEFAULT NULL,
`newsquery` char(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `indicators` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`instrument_id` int(11) DEFAULT NULL,
`date` date DEFAULT NULL,
`sma_5` float(10,3) DEFAULT NULL,
`sma_14` float(10,3) DEFAULT NULL,
`ema_14` float(10,3) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_instrument_indicators` (`instrument_id`),
CONSTRAINT `fk_instrument_indicators` FOREIGN KEY (`instrument_id`) REFERENCES `instruments` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
CREATE TABLE `stockdata` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`instrument_id` int(11) NOT NULL,
`name` char(20) DEFAULT NULL,
`date` date DEFAULT NULL,
`open` float DEFAULT NULL,
`high` float DEFAULT NULL,
`low` float DEFAULT NULL,
`close` float DEFAULT NULL,
`volume` int(11) DEFAULT NULL,
`adjclose` float DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_instrument_stockdata` (`instrument_id`),
CONSTRAINT `fk_instrument_stockdata` FOREIGN KEY (`instrument_id`) REFERENCES `instruments` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
然后使用联接中的索引字段:
SELECT
indicators.date,
instruments.name,
indicators.sma_14,
indicators.sma_5,
stockdata.close
FROM
indicators
INNER JOIN instruments ON (indicators.instrument_id=instruments.id)
INNER JOIN stockdata ON (instruments.id=stockdata.instrument_id)
通过使用索引INT
列,您的联接速度会快得多。使用InnoDB约束将有助于确保数据完整性。
如果您有必要加入name
列的原因,请将它们设置为相同的大小并将其编入索引。
答案 1 :(得分:1)
SELECT
ind.ddate,
ins.name,
ind.sma_14,
ind.sma_5,
sto.close
FROM indicators ind
JOIN instruments ins ON ind.instrument_id = ins.instrument_id
JOIN stockdata sto ON ins.name = sto.name
另一种选择:
select ind.ddate, ins.name, ind.sma_14, ind.sma_5,
(select close from stockdata where name = ins.name limit 1) as close
from indicators ind
join instruments ins on ind.instrument_id = ins.instrument_id
答案 2 :(得分:1)
我怀疑加入了stockdata.name字段。您是否在stockdata和instruments表的名称字段中定义了正确的索引?是否有可能加入名称可能会返回无效结果,您可以加入另一个.id字段吗?
答案 3 :(得分:0)
您正在查询stockdata中的非索引字段名称。创建索引或改为加入id。 (我会做后者,在工具中将名称改为id)