我在MYSQL中有一个很大的基础 - 300 mb,其中有4个表:第一个是大约200mb,第二个是 - 80。 第一张表有150 000条记录,第二张有200 000条记录。
同时我在那里使用内连接。
当我使用优化和indeces时,选择需要3秒(之前需要大约20-30秒)。 这是足够好的结果。但我需要更多,因为页面加载7-8秒(选择3-4,计数1,另一个小查询1秒,1-2页面生成)。
那么,我应该做什么呢? postgres可能比mysql花费更少的时间?或者可能更好地使用memcaches,但在这种情况下它可能需要大量的内存(排序的变种太多)。
可能有人有另一个想法吗?我很高兴听到新的:)
行。我看到我们需要查询:) 我为table_1重命名了字段。
CREATE TABLE `table_1` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`field` varchar(2048) DEFAULT NULL,
`field` varchar(2048) DEFAULT NULL,
`field` int(10) unsigned DEFAULT NULL,
`field` text,
`field` text,
`field` text,
`field` varchar(128) DEFAULT NULL,
`field` text,
`field` text,
`field` text,
`field` text,
`field` text,
`field` varchar(128) DEFAULT NULL,
`field` text,
`field` varchar(4000) DEFAULT NULL,
`field` varchar(4000) DEFAULT NULL,
`field` int(10) unsigned DEFAULT '1',
`field` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`field` text,
`new` tinyint(1) NOT NULL DEFAULT '0',
`applications` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `indexNA` (`new`,`applications`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=153235 DEFAULT CHARSET=utf8;
CREATE TABLE `table_2` (
`id_record` int(10) unsigned NOT NULL AUTO_INCREMENT,
`catalog_name` varchar(512) NOT NULL,
`catalog_url` varchar(4000) NOT NULL,
`parent_id` int(10) unsigned NOT NULL DEFAULT '0',
`checked` tinyint(1) NOT NULL DEFAULT '0',
`level` int(10) unsigned NOT NULL DEFAULT '0',
`work` int(10) unsigned NOT NULL DEFAULT '0',
`update` int(10) unsigned NOT NULL DEFAULT '1',
`type` int(10) unsigned NOT NULL DEFAULT '0',
`hierarchy` varchar(512) DEFAULT NULL,
`synt` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id_record`,`type`) USING BTREE,
KEY `rec` (`id_record`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=14504 DEFAULT CHARSET=utf8;
CREATE TABLE `table_3` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`id_table_1` int(10) unsigned NOT NULL,
`id_category` int(10) unsigned NOT NULL,
`work` int(10) unsigned NOT NULL DEFAULT '1',
`update` int(10) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `site` (`id_table_1`,`id_category`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=203844 DEFAULT CHARSET=utf8;
有疑问: 1)获得一般计数(不到1秒):
SELECT count(table_1.id) FROM table_1
INNER JOIN table_3 ON table_3.id_table_id = table_1.id
INNER JOIN table_2 ON table_2.id_record = table_3.id_category
WHERE ((table_2.type = 0)
AND (table_3.work = 1 AND table_2.work = 1)
AND (table_1.new = 1))AND 1 IN (table_1.applications)
2)获取有限制的页面列表(需要3到7秒,取决于计数):
SELECT table_1.field, table_1.field, table_1.field, table_1.field, table_2.catalog_name FROM table_1
INNER JOIN table_3 ON table_3.id_table_id = table_1.id
INNER JOIN table_2 ON table_2.id_record = table_3.id_category
WHERE ((table_2.type = 0)
AND (table_3.work = 1 AND table_2.work = 1)
AND (table_1.new = 1))AND 1 IN (table_1.applications) LIMIT 10 OFFSET 10
答案 0 :(得分:3)
不要更改DBMS
我不建议更改您的DBMS,它可能非常具有破坏性。如果您使用了与Postgres不兼容的MySQL特定查询;您可能需要重做整个索引等。即使这样,它也可能无法保证性能的提高。
缓存是一个不错的选择
缓存真的是个好主意。它会减轻您的DBMS负担。如果您有大量读取,轻写,则最适合。这样对象可以在Cache中保留更多时间。 MemcacheD是非常好的缓存机制,而且非常简单。快速扩展网站(如Facebook等)大量使用MemcacheD来减轻数据库的负担。
如何扩大真正的大时间
虽然,您没有非常繁重的数据..所以很可能缓存会对您有所帮助。但是,缓存之前的下一步是基于noSQL
的解决方案,例如Cassandra。我们在我们的应用程序中使用cassandra,我们有大量的读写操作(50:50),数据库非常庞大且快速增长。卡桑德拉表现出色。但是,我想在你的情况下, Cassandra是一种矫枉过正的。
<强>可是... 强>
在此之前,您会深入研究任何严重的变化,我建议您真正研究索引。尝试垂直缩放。查看慢查询。 (搜索slow query logging指令)。希望MySQL在优化这些东西后会更快,你不需要额外的工具。
答案 1 :(得分:2)
您应该查看特定于您使用的最常见/最耗时的查询的索引。检查this post索引的mysql。
答案 2 :(得分:1)
除了其他人提供的所有其他建议外,我对MySQL的性能影响略有改变,并没有肯定。但是,我添加了STRAIGHT_JOIN,因此优化器不会尝试考虑为您加入哪个订单或表。
接下来,我将“AND”条件移动到表2和表2的相应JOIN子句中。 3。
最后,表1到3的连接(在你的帖子中)
table_3.id_table_id = table_1.id
而不是
table_3.id_table_1 = table_1.id
此外,我无法分辨性能,但可能只在“新”列上有一个独立的索引,以便完全匹配,而不考虑“应用程序”列。我不知道复合索引是否导致问题,因为您对应用程序使用“IN”而不是真正的可索引搜索基础。
这是修改后的结果
SELECT STRAIGHT_JOIN
count(table_1.id)
FROM
table_1
JOIN table_3
ON table_1.id = table_3.id_table_1
AND table_3.work = 1
JOIN table_2
ON table_3.id_category = table_2.id_record
AND table_2.type = 0
AND table_2.work = 1
WHERE
table_1.new = 1
AND 1 IN table_1.applications
SELECT STRAIGHT_JOIN
table_1.field,
table_1.field,
table_1.field,
table_1.field,
table_2.catalog_name
FROM
table_1
JOIN table_3
ON table_1.id = table_3.id_table_1
AND table_3.work = 1
JOIN table_2
ON table_3.id_category = table_2.id_record
AND table_2.type = 0
AND table_2.work = 1
WHERE
table_1.new = 1
AND 1 IN table_1.applications
LIMIT 10 OFFSET 10
答案 3 :(得分:0)
您还应优化查询。
答案 4 :(得分:0)
如果不仔细研究这些陈述,这个问题只能用理论方法来回答。只需要考虑一些想法......
SELECT-Statement ...
首先,确保您的查询尽可能“好”。你可能错过了任何可能吗?那些indeces是相同的字段类型等等吗?您是否可以缩小查询范围,以便数据库可以减少工作量?
查询缓存...
如果您的查询经常重复,可能有助于使用Query cache或 - 如果您已经在使用它 - 请为其提供更多内存。
硬件......
当然,不同的RDBMS比其他RDBMS更慢或更快,具体取决于它们的优势或劣势,但如果您的查询被优化为遗忘,您只能在扩展数据库服务器时更快地获得它(更好的cpu,更好的i / o等等,取决于瓶颈的位置)。
其他因素......
如果全部最大化,可能会尝试加速其他组件(1-2秒的页面生成对我来说看起来很慢)。
对于提及的所有因素,stackoverflow.com中有大量的想法和帖子。
答案 5 :(得分:0)
这实际上并不是一个如此庞大的数据库,对您的数据库系统来说肯定不会太多。作为比较,我们使用的数据库目前大约为40 GB。但它是一个MS SQL Server,所以它不能直接比较,但数据库系统之间没有显着差异。
我的猜测是你还没有完全成功地使用索引来加速查询。您应该查看查询的执行计划,看看是否可以发现大部分时间执行的执行部分。