代理和自然键之间存在一场健康的辩论:
我的观点似乎与大多数人(这是一个微不足道的多数)一致,你应该使用代理键,除非自然键是完全明显的并且保证不会改变.然后你应该对自然键强制执行唯一性.这几乎意味着代理键几乎所有的时间.
这两种方法的示例,从Company表开始:
1:代理键:表具有ID字段,即PK(和标识).公司名称必须按州独特,因此存在唯一约束.
2:自然键:表使用CompanyName和State作为PK - 满足PK和唯一性.
假设公司PK用于其他10个表中.我的假设,没有数字可以支持,这就是代理关键方法在这里要快得多.
我在自然键中看到的唯一令人信服的论据是使用两个外键作为自然键的多对多表.我认为在这种情况下它是有道理的.但如果你需要重构,你可能会遇到麻烦; 我认为这超出了这篇文章的范围.
有没有人看到,比较的一篇文章的性能差异在一组使用表的代理键 与同一组使用表的自然键?环顾SO和谷歌并没有产生任何有价值的东西,只是大量的理论研究.
重要更新:我已经开始构建一组回答这个问题的测试表.它看起来像这样:
每个部件都连接到一个工厂,工厂的每个部件都与工程师联系在一起.如果有人对这个测试床有问题,现在是时候了.
database database-design key primary-key database-performance
我有一个伙伴为一个列出待售汽车的人运行一个网络应用程序.有几千个客户使用它,每个客户在数据库中有数百甚至数千行(有些已经持续了5年,每月销售数百辆汽车,每次销售10行(评论,消息,等等)).他已经在一个SQL Server数据库中运行这个系统,在一个物理服务器中使用20GB或RAM,并且一直使用几个处理器,没有任何问题.这是某种奇迹吗?
就像大多数程序员一样,我不是DBA而且只是过去了,感谢ORMs等.无论我看到什么,人们都在讨论是否需要为Web应用程序的大用户进行分片或获取单独的数据库服务器.为什么是这样?拥有大量或多行的大型DB是否真的效率低下?我是否应该计划使用Cassandra或其他东西,或者我可以依靠与Postgres一起扩展吗?
我现在有一些查询耗时太长(300毫秒),因为数据库已经增长到几百万条记录.幸运的是,对我来说,查询不需要查看大部分数据,最新的100,000条记录就足够了,所以我的计划是维护一个包含最新100,000条记录的单独表格并针对此运行查询.如果有人对更好的方法有任何建议,这将是伟大的.我真正的问题是,如果查询确实需要针对历史数据运行,有哪些选项,下一步是什么?我想到的事情:
这些事情是否正确,还有其他选择吗?某些数据库提供程序是否具有比其他数据库提供程序更多的功能来处理这些问题,例如将特定的表/索引指定为完全在内存中?
对不起,我应该提到这个,我正在使用mysql.
我忘了在上面提到索引.到目前为止,索引是我唯一的改进来源.为了识别瓶颈,我一直在使用maatkit进行查询,以显示是否正在使用索引.
我知道我现在正在远离问题的目的,所以也许我应该再做一个.我的问题是EXPLAIN说查询需要10毫秒而不是300毫秒jprofiler报告.如果有人有任何建议我会非常感激.查询是:
select bv.*
from BerthVisit bv
inner join BerthVisitChainLinks on bv.berthVisitID = BerthVisitChainLinks.berthVisitID
inner join BerthVisitChain on BerthVisitChainLinks.berthVisitChainID = BerthVisitChain.berthVisitChainID
inner join BerthJourneyChains on BerthVisitChain.berthVisitChainID = BerthJourneyChains.berthVisitChainID
inner join BerthJourney on BerthJourneyChains.berthJourneyID = BerthJourney.berthJourneyID
inner join TDObjectBerthJourneyMap on BerthJourney.berthJourneyID = TDObjectBerthJourneyMap.berthJourneyID
inner join TDObject on TDObjectBerthJourneyMap.tdObjectID = TDObject.tdObjectID
where
BerthJourney.journeyType='A' and
bv.berthID=251860 and
TDObject.headcode='2L32' and
bv.depTime is null and
bv.arrTime > '2011-07-28 16:00:00'
Run Code Online (Sandbox Code Playgroud)
而输出来自EXPLAIN:
+----+-------------+-------------------------+-------------+---------------------------------------------+-------------------------+---------+------------------------------------------------+------+-------------------------------------------------------+
| id | select_type …Run Code Online (Sandbox Code Playgroud) 我正在开发一个存储图像和相关元数据的应用程序.我在使用NHibernate执行某个查询时遇到了问题.查询花费了太长时间(在我的机器上大约31秒),尽管在SQL Server Management Studio中执行时相同的查询只需要几分之一秒.
我已经将问题简化并解决了一个小的测试应用程序:
实体:
标记,由Id组成(字符串,标记值本身)
public class Tag
{
public virtual string Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
图像,包括Id(int),Name(字符串)和标签(多对多,Tag实例集)
public class Image
{
private Iesi.Collections.Generic.ISet<Tag> tags = new HashedSet<Tag>();
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IEnumerable<Tag> Tags
{
get { return tags; }
}
public virtual void AddTag(Tag tag)
{
tags.Add(tag);
}
}
Run Code Online (Sandbox Code Playgroud)
我使用"按代码映射"使用以下映射:
public class TagMapping : ClassMapping<Tag>
{
public TagMapping() …Run Code Online (Sandbox Code Playgroud) 这种情况是否可以接受?
AND DATEDIFF(month,p.PlayerStatusLastTransitionDate,@now) BETWEEN 1 AND 7)
Run Code Online (Sandbox Code Playgroud)
我的经验法则是左边的一个函数使条件不可思议..但在某些地方我已经读过BETWEEN子句是可以理解的. 所有人都知道吗?
以供参考:
注意:如果任何大师在此结束,请更新Sargable Wikipedia页面.我更新了一点,但我相信它可以改进:)
看起来SQL Server不会自动使用CHECKSUM /哈希索引,除非CHECKSUM列明确包含在查询的搜索参数中.这是一个问题,因为我不控制查询表的应用程序,我可能不会破坏它们的性能.
有没有办法让SQL Server使用新的CHECKSUM /哈希索引而不修改查询以包含新的CHECKSUM /哈希列?
CREATE TABLE big_table
(
id BIGINT IDENTITY CONSTRAINT pk_big_table PRIMARY KEY,
wide_col VARCHAR(50),
wide_col_checksum AS CHECKSUM(wide_col),
other_col INT
)
CREATE INDEX ix_checksum ON big_table (wide_col_checksum)
Run Code Online (Sandbox Code Playgroud)
插入一些测试数据:
SET NOCOUNT ON
DECLARE @count INT = 0
BEGIN TRANSACTION
WHILE @count < 10000
BEGIN
SET @count = @count + 1
INSERT INTO big_table (wide_col, other_col)
VALUES (SUBSTRING(master.dbo.fn_varbintohexstr(CRYPT_GEN_RANDOM(25)), 3, 50), @count)
IF @count % 1000 = 0
BEGIN
COMMIT TRANSACTION
BEGIN TRANSACTION
END
END …Run Code Online (Sandbox Code Playgroud) sql-server indexing hash sql-server-2008 database-performance
我有2200万条记录的大桌子.我想执行下一个查询:
select auto_alerts from alerts_stat where endDate > "2012-12-01"
Run Code Online (Sandbox Code Playgroud)
为了提高性能,我为endData字段添加了BTREE索引:
CREATE INDEX endDate_index USING BTREE ON alerts_stat(endDate)
Run Code Online (Sandbox Code Playgroud)
在我开始分析查询执行计划之后:
当我想在15到7天之前获取参数时:
explain select alerts_sp from alerts_stat
where endDate between CURDATE() - 15 and CURDATE() - 7;
Run Code Online (Sandbox Code Playgroud)
我有下一个执行计划来处理2,762,088行.
'1', 'SIMPLE', 'browser_plugin_alerts_stat', 'range', 'endDate_index', 'endDate_index', '4', NULL, '2762088', 'Using where'
Run Code Online (Sandbox Code Playgroud)
当我将间隔增加一天时,我收到了:
explain select alerts_sp from alerts_stat
where endDate between CURDATE() - 15 and CURDATE() - 6;
Run Code Online (Sandbox Code Playgroud)
EXPLAIN表示MySQL计划处理所有22,923,126行.
'1', 'SIMPLE', 'browser_plugin_alerts_stat', 'ALL', 'endDate_index', NULL, NULL, NULL, '22932390', 'Using where'
Run Code Online (Sandbox Code Playgroud)
例如,在WHERE过程22,925,642中没有任何条件地选择.
我可以改进执行计划吗?也许我在某个地方有错误,或者是正常的MySQL行为?
mysql performance database-performance sqldatetime database-indexes
我使用Talend将数据加载到sql-server数据库中.
看来我工作中最薄弱的部分不是数据处理,而是数据库中的有效负载,不超过17行/秒.
有趣的一点是,我可以同时启动5个工作,并且它们都将以17个/秒的速度加载.
什么可以解释这种缓慢,我怎样才能提高速度?
谢谢
新信息:
我的桌面和服务器之间的传输速度大约是1MByte
我的工作每10 000工作一次
我使用sql server 2008 R2
我用于工作的模式是这样的:

我正在使用亚马逊的RDS数据库和一些非常大的表,昨天我开始面临服务器上100%的CPU利用率和一堆以前没有发生的慢速查询日志.
我试图检查正在运行的查询并从explain命令面对此结果
+----+-------------+-------------------------------+--------+----------------------------------------------------------------------------------------------+---------------------------------------+---------+-----------------------------------------------------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------------------------+--------+----------------------------------------------------------------------------------------------+---------------------------------------+---------+-----------------------------------------------------------------+------+----------------------------------------------+
| 1 | SIMPLE | businesses | const | PRIMARY | PRIMARY | 4 | const | 1 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | activities_businesses | ref | PRIMARY,index_activities_users_on_business_id,index_tweets_users_on_tweet_id_and_business_id | index_activities_users_on_business_id | 9 | const | 2252 | Using index condition; Using where |
| 1 | SIMPLE …Run Code Online (Sandbox Code Playgroud) mysql database-performance query-performance amazon-rds mysql-slow-query-log
背景
我有一个MySQL测试环境,其中的表包含2亿多行。在此表上必须执行两种类型的查询;
client_id和的列表,sgtin最多可容纳50.000个项目,我需要知道sgtin表中存在哪些。client_id和的列表,sgtin最多可容纳50.000个项目,我需要提取整行。(商店,gtin ...)对于单个“ client_id”,该表可以增长到200+百万条记录。
测试环境
至强E3-1545M / 32GB RAM / SSD。InnoDB缓冲池24 GB。(生产将是具有192GB RAM的更大服务器)
表
CREATE TABLE `sgtins` (
`client_id` INT UNSIGNED NOT NULL,
`sgtin` varchar(255) NOT NULL,
`store` varchar(255) NOT NULL,
`gtin` varchar(255) NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX (`client_id`, `store`, `sgtin`),
INDEX (`client_id`),
PRIMARY KEY (`client_id`,`sgtin`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Run Code Online (Sandbox Code Playgroud)
测验
首先,我生成了随机的sgtin值,这些值分布在10个“ client_id”上,以用2亿行填充表格。
我创建了一个基准工具,该工具可以执行尝试的各种查询。另外,我还使用了解释计划来找出最佳性能。对于每次测试,该工具都会从我用来填充数据库的数据中读取新的随机数据。确保每个查询都是不同的。
对于这篇文章,我将使用28 sgtins。
临时表
CREATE TEMPORARY TABLE sgtins_tmp_table (`sgtin` …Run Code Online (Sandbox Code Playgroud) mysql ×4
database ×3
sql ×3
sql-server ×3
amazon-rds ×1
caching ×1
hash ×1
indexing ×1
key ×1
performance ×1
primary-key ×1
scalability ×1
sqldatetime ×1
talend ×1
temp-tables ×1
upsert ×1