我将每个交易日的所有股权交易存入表中。该表包含数百万行。因为在同一时间和第二次,可能发生2次或更多次事务,并且源数据也没有任何主键。所以我没有向表中添加任何主键。但是做任何查询都非常慢,大约60到120秒。
这里有结构:mysql,innodb,utf8_general_ci
Ticker varchar(15)
ReleaseDT datetime
Order int(1)
Price decimal (7,3)
Volume bigint(13)
Amount bigint(13)
NoOfLot int(11)
Session varchar(3)
Source varchar(15)
TimeStamp timestamp
功能:
问题: 1.由于没有我能找到的唯一项目,此表的主键是否会影响查询速度?
我只需要添加一个类似ID的auto_incremental#,它会自行创建吗?它对查询速度有帮助吗?
有些查询需要我60-120秒,有什么方法可以改进上表吗?喜欢索引?如果是,请告知如何。
我将使用php进行Web查询和输出,有时使用vb.net从mysql服务器进行查询。
示例:
select Ticker, ReleaseDT as 'Last Update',Price, convert(sum(case when iOrder = 1 then Amount else 0 end ),decimal(9,0)) as TtlBuyAmt,
convert(sum(case when iOrder = -1 then Amount else 0 end ),decimal(9,0)) as TTlSellAmt,
convert(sum(case when iOrder = 0 then Amount else 0 end ),decimal(9,0)) as TTlUndetAmt,
convert(sum(case when iOrder = 1 then Amount else 0 end ) / sum(case when iOrder = -1 then Amount else 0 end),decimal(9,0)) as TTlBuySellRatio,
sum(case when iOrder = 1 and Session = 'AM' then Amount else 0 end ) as BuyAmtAM ,
SUM(CASE WHEN iOrder = 1 and Session = 'PM' then Amount else 0 end ) as BuyAmtPM ,
SUM(CASE WHEN iOrder = -1 and Session = 'AM' then Amount else 0 end) as SellAmtAM,
SUM(CASE WHEN iOrder = -1 and Session = 'PM' then Amount else 0 end ) as SellAmtPM ,
convert(SUM(CASE WHEN iOrder = -1 and Session = 'PM' then Amount else 0 end ) / SUM(CASE WHEN iOrder = -1 and Session = 'AM' then Amount else 0 end),decimal(5,2)) as SellPMAMRatio,
sum(Amount) as TotalAmt,
convert(sum(case when iOrder = 1 then Amount else 0 end ) - sum(case when iOrder = -1 then Amount else 0 end ),decimal(9,0)) as NetAmount
FROM Trade
WHERE Ticker = '1 HK EQUITY' and DATE(ReleaseDT) between '20150102' and '20150104'
GROUP BY Ticker, date(ReleaseDT), Price
ORDER BY Ticker ASC, Price DESC
运行时需要> 60秒才能改进?
SELECT * FROM AS2046.BlockTrade_EOD where Ticker = '1 HK EQUITY' and Date(ReleaseDT) > '20150102' Group by Price
使用EXPLAIN ...并且结果如下:
# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
'1', 'SIMPLE', 'BlockTrade_EOD', 'ALL', NULL, NULL, NULL, NULL, '2327212', 'Using where; Using temporary; Using filesort'
答案 0 :(得分:1)
唯一的,自动递增的主键有很多原因 - 例如,当您想要更新或删除数据时。但是,如果您没有外键关系,则不一定非必要。
对于您的查询,复合索引应该有所帮助:
create index idx_Trade_ReleaseDT on Trade(Ticker, ReleaseDT)
但是,您需要修复where
子句。如果ReleaseDt
没有时间组件,请使用:
WHERE Ticker = '1 HK EQUITY' and
ReleaseDT between DATE('2015-01-02') and DATE('2015-01-04')
或者,如果ReleaseDT
可以有时间组件:
WHERE Ticker = '1 HK EQUITY' and
ReleaseDT >= DATE('2015-01-02') and
ReleaseDT < DATE('2015-01-05')
答案 1 :(得分:0)
因为这仍是一个相当广泛的问题,输入非常有限,我会尝试提供一些有限的建议:
主键不一定会加快查询速度。这在很大程度上取决于您的查询类型。通常索引(不一定是主键)从您发布的查询中,似乎有可能,Ticker上的索引(不是主键,因为Ticker不是唯一的,因为它似乎)可能加速操作(“WHERE Tickler ='...'“)。 ReleaseDT也是索引的候选者 - 可能与Ticker一起。但所有这些都取决于表格中的数据...例如:有多少行的Ticker值为“1 HK EQUITY”。
添加人工PK加速操作的可能性非常小。许多数据库自己添加了人工PK。另外,我没有看到人工PK如何帮助这个选择。当然,主键在其他选择中可能很有用。
请参阅1.我的最佳猜测是针对索引的Ticker和/或ReleaseDT(甚至是PK,具体取决于您的数据)。您看到的很可能是“全表扫描” - 数据库引擎必须为一个SELECT处理所有百万行。索引可以大大减少操作 - 取决于数据库中的数据。
我建议检查表的内容(例如,有多少行包含“1 HK EQUITY”作为Ticker。如果只有一小部分行这样做,则开始在此行上添加索引。
但是:注意 - 表上的每个索引都会增加对表的所有写入的复杂性,因为必须维护索引。
如需进一步的建议,则需要更多数据!
答案 2 :(得分:0)
首先,ReleaseDT应该是DATETIME,而不仅仅是DATE?假设有一个TIME组件......
如果表是InnoDB,那么真的应该有一个明确的PRIMARY KEY。 (如果是MyISAM,那没关系。(请提供SHOW CREATE TABLE)
添加复合索引INDEX(Ticker, ReleaseDT)
。 AND 不会隐藏函数内的列,例如DATE(ReleaseDT)
。这使得无法使用索引。正如@Gordon所说,但更简单:
ReleaseDT >= '2015-01-02' and
ReleaseDT < '2015-01-05'
如果我知道有多少天并且不想玩日期算术,我更喜欢这个:
ReleaseDT >= '2015-01-02' and
ReleaseDT < '2015-01-02' + INTERVAL 3 DAY
无需更改
GROUP BY Ticker, date(ReleaseDT), Price
也许
convert(sum(case when iOrder = -1 then Amount else 0 end ),decimal(9,0))
可以简化为
SUM(IF(iOrder = -1, Amount, 0))
如果ReleaseDT可以是DATE,则PRIMARY KEY(Ticker,ReleaseDT)可能更好。