【发布时间】:2015-05-04 22:20:18
【问题描述】:
这听起来很奇怪,但我们有一个包含millions 行数据的表,并且我们正在使用JOIN、AND、ORDER BY 等操作运行查询,因为查询运行缓慢,查询扫描全表并找到最佳匹配结果,目前单个查询需要 2 到 3 秒,这是不可接受的:(
我可以在Memory 中加载完整表并对其进行读取操作吗?我们没有在表中写入数据,因此我们不关心power off 上的数据丢失,如果需要,我们可以再次将表快速加载到内存中。
我已经使用mysqltunner 尝试了所有自定义等,但没有帮助。
您是否建议在内存中加载表将有助于read 操作?
我们的其他解决方案是sqlite 将文件放在memory 上并对其运行查询。
表:
| lcr | CREATE TABLE `lcr` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`digits` varchar(15) DEFAULT NULL,
`rate` float(11,5) unsigned DEFAULT NULL,
`intrastate_rate` float(11,5) unsigned DEFAULT NULL,
`intralata_rate` float(11,5) unsigned DEFAULT NULL,
`carrier_id` int(11) NOT NULL,
`lead_strip` int(11) NOT NULL,
`trail_strip` int(11) NOT NULL,
`prefix` varchar(16) NOT NULL,
`suffix` varchar(16) NOT NULL,
`lcr_profile` int(11) NOT NULL DEFAULT '0',
`date_start` datetime NOT NULL DEFAULT '1970-01-01 00:00:00',
`date_end` datetime NOT NULL DEFAULT '2030-12-31 00:00:00',
`quality` float(10,6) NOT NULL,
`reliability` float(10,6) NOT NULL,
`cid` varchar(32) NOT NULL DEFAULT '',
`enabled` tinyint(1) NOT NULL DEFAULT '1',
`lrn` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `carrier_id` (`carrier_id`),
KEY `digits` (`digits`),
KEY `lcr_profile` (`lcr_profile`),
KEY `rate` (`rate`),
KEY `digits_profile_cid_rate` (`digits`,`rate`) USING BTREE,
CONSTRAINT `carrier_id` FOREIGN KEY (`carrier_id`) REFERENCES `carriers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1130954 DEFAULT CHARSET=latin1 |
在表中,我们有以下数据。总行数约 120 万行
mysql> select * from lcr LIMIT 0,10;
+-----+--------+---------+-----------------+----------------+------------+------------+-------------+--------+--------+-------------+---------------------+---------------------+----------+-------------+-----+---------+-----+
| id | digits | rate | intrastate_rate | intralata_rate | carrier_id | lead_strip | trail_strip | prefix | suffix | lcr_profile | date_start | date_end | quality | reliability | cid | enabled | lrn |
+-----+--------+---------+-----------------+----------------+------------+------------+-------------+--------+--------+-------------+---------------------+---------------------+----------+-------------+-----+---------+-----+
| 1 | 91 | 0.00010 | NULL | NULL | 13 | 0 | 0 | | | 0 | 2015-09-11 15:53:39 | 2015-02-28 00:00:00 | 0.000000 | 0.000000 | | 1 | 0 |
| 2 | 91 | 0.01000 | NULL | NULL | 13 | 0 | 0 | | | 0 | 2015-09-11 15:53:39 | 2015-02-28 00:00:00 | 0.000000 | 0.000000 | | 1 | 0 |
| 8 | 1 | 0.00700 | NULL | NULL | 13 | 0 | 0 | | | 0 | 2013-09-11 16:56:38 | 2015-02-28 00:00:00 | 0.000000 | 0.000000 | | 0 | 0 |
| 9 | 91 | 0.00100 | NULL | NULL | 13 | 0 | 0 | | | 0 | 2015-09-11 15:53:39 | 2015-02-28 00:00:00 | 0.000000 | 0.000000 | | 0 | 0 |
| 130 | 1844 | 0.00000 | NULL | NULL | 13 | 0 | 0 | | | 0 | 2013-12-08 20:03:45 | 2015-02-28 00:00:00 | 0.000000 | 0.000000 | | 1 | 0 |
| 131 | 998 | 0.07070 | NULL | NULL | 13 | 0 | 0 | | | 0 | 2014-02-11 09:20:00 | 2015-02-28 00:00:00 | 0.000000 | 0.000000 | | 1 | 0 |
| 132 | 9989 | 0.09490 | NULL | NULL | 13 | 0 | 0 | | | 0 | 2014-02-11 09:20:00 | 2015-02-28 00:00:00 | 0.000000 | 0.000000 | | 1 | 0 |
| 133 | 99899 | 0.09490 | NULL | NULL | 13 | 0 | 0 | | | 0 | 2014-02-11 09:20:00 | 2015-02-28 00:00:00 | 0.000000 | 0.000000 | | 1 | 0 |
| 134 | 99898 | 0.09490 | NULL | NULL | 13 | 0 | 0 | | | 0 | 2014-02-11 09:20:00 | 2015-02-28 00:00:00 | 0.000000 | 0.000000 | | 1 | 0 |
| 135 | 99897 | 0.09490 | NULL | NULL | 13 | 0 | 0 | | | 0 | 2014-02-11 09:20:00 | 2015-02-28 00:00:00 | 0.000000 | 0.000000 | | 1 | 0 |
+-----+--------+---------+-----------------+----------------+------------+------------+-------------+--------+--------+-------------+---------------------+---------------------+----------+-------------+-----+---------+-----+
10 rows in set (0.00 sec)
查询:
mysql> SELECT l.digits AS lcr_digits, c.carrier_name AS lcr_carrier_name, l.rate AS lcr_rate_field, cg.prefix AS lcr_gw_prefix, cg.suffix AS lcr_gw_suffix, l.lead_strip AS lcr_lead_strip, l.trail_strip AS lcr_trail_strip, l.prefix AS lcr_prefix, l.suffix AS lcr_suffix, cg.codec AS lcr_codec, l.cid AS lcr_cid FROM lcr l JOIN carriers c ON l.carrier_id=c.id JOIN carrier_gateway cg ON c.id=cg.carrier_id WHERE c.enabled = '1' AND cg.enabled = '1' AND l.enabled = '1' AND ( (digits IN (16623033747, 1662303374, 166230337, 16623033, 1662303, 166230, 16623, 1662, 166, 16, 1) AND lrn = false) OR (digits IN (16623033747, 1662303374, 166230337, 16623033, 1662303, 166230, 16623, 1662, 166, 16, 1) AND lrn = true)) AND CURRENT_TIMESTAMP BETWEEN date_start AND date_end ORDER BY digits DESC, rate, rand();
+------------+------------------+----------------+---------------+-------------------------+----------------+-----------------+------------+------------+-----------+---------+
| lcr_digits | lcr_carrier_name | lcr_rate_field | lcr_gw_prefix | lcr_gw_suffix | lcr_lead_strip | lcr_trail_strip | lcr_prefix | lcr_suffix | lcr_codec | lcr_cid |
+------------+------------------+----------------+---------------+-------------------------+----------------+-----------------+------------+------------+-----------+---------+
| 1662303 | abc | 0.00395 | | @sip.abc.com | 0 | 0 | | | | |
| 1 | xyz | 0.00980 | 73734599* | @sip.xyz.com | 0 | 0 | | | | |
| 1 | Silver | 0.01020 | | @sip.Silver.com | 0 | 0 | | | | |
+------------+------------------+----------------+---------------+-------------------------+----------------+-----------------+------------+------------+-----------+---------+
3 rows in set (2.06 sec)
它使用查询提供的数字扫描digit,并从其他表中查找值,但这些表非常小,只有很少的条目,它占用了2 sec,但是当多个查询运行时,它会达到CPU负载。
【问题讨论】:
-
FLOAT(m,n) 几乎总是“错误的”。它说 (1) 舍入到“n”个小数位,然后舍入到 FLOAT 的二进制精度。另外,如果数字大于 m & n 指定的值,它会说要做一些讨厌的事情。为什么有两个四舍五入?使用 DECIMAL(m,n) 或普通 FLOAT。
标签: mysql sql sql-server performance sqlite