SQL Databases Don't Scale (简译)

本文深入探讨了SQL数据库扩展性的核心概念,包括横向扩展、分区、共享和只读slave等技术,以及它们如何应对扩展性需求,同时指出这些方法存在的局限性。

我经常问的一个问题是:你是如何来扩展SQL Database的?有很多的方法可以做到,比如使用缓存,共享或者用其他的技术将压力从数据库释放,但实际上我们没有。SQL Database从根本上来说是不具有扩展性的,我们也没有魔法使它忽然具有扩展性。

什么是扩展性?

必须具有几下几点:

   1. 横向扩展:更多的server可以带来更高的性能。
   2. 对应用程序的透明性:扩展的实现对于业务逻辑来说是透明的,逻辑上只有一个server服务于业务。
   3. 单点失败不会导致故障:单个server或者节点的宕机不会导致系统的失败。

接下来,让我们看一些技术如何“扩展”SQL Database以及他们为什么没有达到以上几点。

纵向扩展

一种方法去扩展SQL Database是买更大的server或者存储。这带来的问题是:

   1. 运输变的复杂
   2. 原来的机器落后,升级变的浪费资源
   3. 你不知道到底类似容量这样的问题会变的有多大

这个不符合扩展性的第一条。

分区,共享

根据逻辑对数据进行分区。这种方法也是纵向扩展的一种方法,它紧密依赖于应用并且你需要仔细的去计划你的schema。

这种方法对于程序来说是不透明的,必须和业务结合在一起,不符合扩展性的第二条。更严重的问题是,数据库是关系数据库,存储的数据也是相关的,这样的相关数据分布在多个server上,你需要为这样重复的关系服务,而且当他们返回时必须在客户端重新构建这样的关系。

只读的Slave

MySql的杀手级应用就是配置方便的master-slave复制,你可以用一个read-only-slave来处理你的读应用而把所有的 insert update delete都由master来处理。

这种方式是最好的扩展方式,这也是很多大型的MySql在使用的方法。对于读扩展来说这样的方法是好的,对于写扩展来说这样的效率还是不行的,而且当你维护master server的时候,也会造成整个系统的宕机。

原文:http://adam.blog.heroku.com/past/2009/7/6/sql_databases_dont_scale/

<think> 首先,用户的问题是:“我想查找SQL语句中Money LONG DEFAULT 1000报错的解决方案”。用户提到在SQL创建表语句中使用了"MONEY LONG DEFAULT 1000",但报错了,需要解决这个问题。 从站内引用看: - 引用[1]展示了SQL创建表的基本语法,包括列定义如"Id_P int"。 - 引用[2]展示了一个MySQL例子,有CHECK约束,但数据类型是int和varchar。 - 引用[3]是关于动态SQL的,涉及MyBatis的where标签,不直接相关。 用户的问题焦点在"MONEY LONG DEFAULT 1000"报错。我需要回忆SQL数据类型: - "LONG" 可能不是标准SQL数据类型。在SQL中,常见的数据类型包括INT、BIGINT、VARCHAR等。 - "MONEY" 可能是一个自定义列名,但问题在于数据类型部分。 - 在SQL中,"LONG" 通常不是标准类型;在MySQL中,INT或BIGINT用于整数,在Oracle中可能有LONG类型,但它是过时的或不推荐使用的。 - 报错可能源于数据类型无效或语法错误。 常见SQL数据类型: - 在MySQL中,整数类型有:TINYINT、SMALLINT、INT、BIGINT。"LONG" 不是标准;或许用户意指BIGINT? - "MONEY" 作为列名应该没问题,但数据类型部分有问题。 - "DEFAULT 1000" 的意思是默认值为1000,这在语法上应该正确,因为1000是数字。 可能的原因: 1. 数据类型无效:"LONG" 可能不被数据库支持。例如: - In MySQL, use BIGINT for large integers. - Or, perhaps they meant DECIMAL or NUMERIC for monetary values, as money should be stored with precision. - 货币值通常使用DECIMAL或NUMERIC存储,以避免浮点误差。 用户指定了"DEFAULT 1000",这隐含数据类型是数值类型。但"LONG"可能错误。 在引用中: - 引用[2]有"Age int, CHECK (Age>=18)",所以数据类型是INT。 - 没有提到LONG类型。 所以,解决方案可能是更改数据类型。 步骤: 1. 识别数据库系统:用户没有指定,但从引用看,引用[2]是MySQL,引用[3]是MyBatis用于Java,可能涉及MySQL或其他。但用户问题中没指定,所以要给出通用建议或询问。 - 在回答中,我可以假设是MySQL或其他常见系统。 2. 建议更改数据类型: - 对于货币,最好使用DECIMAL(precision, scale) 或 NUMERIC。 - 例如,DECIMAL(10, 2) for values like 1000.00. - 如果用户坚持整数,使用BIGINT或INT。 3. Syntax error: In SQL, the syntax is CREATE TABLE table_name (column_name data_type DEFAULT default_value, ...). - Here, "MONEY LONG DEFAULT 1000" – if "LONG" is not a valid data type, it causes error. 4. Specific database differences: - In MySQL, LONG is an alias for MEDIUMTEXT, which is for text, not numbers. Using it with DEFAULT 1000 might cause type mismatch. - In Oracle, LONG is for large character data. - Better to use appropriate numeric type. Possible solution: - Change "LONG" to a numeric data type like INT, BIGINT, or DECIMAL. For example: - CREATE TABLE your_table ( Money BIGINT DEFAULT 1000, ...); or - CREATE TABLE your_table ( Money DECIMAL(10,2) DEFAULT 1000.00, ...); for monetary values. Also, ensure the syntax is correct. From the error perspective, if it's a type error, changing the type should fix it. Now, structure my answer: - Since the system instruction says to use Chinese, I'll respond in Chinese. - Answer should be clear, step-by-step. - Use $...$ for inline math, but here no math, so probably not needed. - Use $$...$$ for standalone formulas if any, but SQL code might be in code blocks. - Reference the citations naturally. From the refs, ref[1] shows basic CREATE TABLE, ref[2] has NOT NULL and CHECK, but not directly related. I can mention that data types should be valid as per SQL standards. - Also, generate related questions at the end. User's previous question might be implied, but in this session, the visible context starts with this message. The system prompt says "参考用户上一次的问题和你的回答", but previous is the system instruction itself. So, I'll base on the current query. Finally, generate related questions. Answer outline: 1. Acknowledge the error: Many SQL databases don't recognize "LONG" as a numeric data type, causing errors. 2. Explain the issue: "LONG" is often for text or large objects, not for numbers. Using it with DEFAULT 1000 (a number) leads to type incompatibility. 3. Provide solution: Change the data type to a numeric one like BIGINT or DECIMAL. 4. Give example: e.g., CREATE TABLE Persons ( ..., Money BIGINT DEFAULT 1000, ...); 5. Suggest using DECIMAL for money to handle decimal points. 6. Refer to citations subtly: As shown in reference [1] and [2], valid data types are used. 7. Code block for clarity. Related questions ideas: 1. 如何选择SQL中合适的数据类型? 2. SQL中货币值的存储最佳实践? 3. CREATE TABLE语句的其他常见错误和解决方案。 Ensure language is Chinese. </think> ### SQL创建表语句中Money LONG DEFAULT 1000报错的解决方案 您在SQL创建表语句中使用`Money LONG DEFAULT 1000`时遇到报错,这通常是因为`LONG`不是一个有效的数值数据类型或与数据库系统不兼容。`LONG`在大多数SQL数据库中是保留用于文本或大对象存储(如Oracle的CLOB类型),而不是数值类型。将其与数字默认值`DEFAULT 1000`一起使用会导致数据类型冲突或语法错误。下面我将逐步解释原因并提供解决方案,确保语法正确。 #### 错误原因分析 1. **无效的数据类型**: - `LONG`在SQL标准中通常用于存储长文本(如MySQL中的`LONGTEXT`或Oracle中的`LONG`),它不支持数值运算或默认数值值。 - 当您指定`DEFAULT 1000`时,数据库期望一个数值类型(如INT、BIGINT或DECIMAL),但`LONG`被视为文本类型,导致类型不匹配错误。例如,在MySQL中尝试此操作会报错:`Incorrect column specifier for column 'Money'`。 - 引用[1]和[2]展示了正确的数据类型使用,如`Id_P int`或`Age int`,未使用`LONG`用于数值列[^1][^2]。 2. **数据库系统差异**: - 不同数据库系统对数据类型的支持不同: - **MySQL**:`LONG`是`MEDIUMTEXT`的别名,用于文本。数值类型应使用`INT`, `BIGINT`, 或`DECIMAL`。 - **SQL Server**:`LONG`不直接存在,数值类型用`INT`或`MONEY`。 - **Oracle**:`LONG`用于字符数据,数值类型用`NUMBER`。 - 您的语句可能因数据库系统而异,但`LONG DEFAULT 1000`在多数情况下无效。 3. **货币值的特殊考虑**: - 存储货币值时,建议使用精确数值类型(如`DECIMAL`或`NUMERIC`)以避免浮点误差,而不是整数类型。`DEFAULT 1000`可以工作,但可能丢失小数精度。 #### 解决方案 修改`Money`列的数据类型为合适的数值类型,并确保默认值语法正确。以下是修复后的通用SQL语句(兼容主流数据库如MySQLSQL Server): ```sql -- 推荐使用DECIMAL或NUMERIC处理货币值(支持小数) CREATE TABLE your_table ( Money DECIMAL(10, 2) DEFAULT 1000.00, -- DECIMAL(precision, scale):精度10位,小数2位 -- 其他列定义... ); -- 如果只需整数,使用BIGINT或INT CREATE TABLE your_table ( Money BIGINT DEFAULT 1000, -- BIGINT用于大整数 -- 其他列定义... ); ``` **关键修改说明**: - **更改数据类型**: - 将`LONG`替换为`DECIMAL(10, 2)`:这是存储货币的最佳实践,例如`DECIMAL(10, 2)`允许最大99999999.99的值,默认值设为1000.00。 - 或使用`BIGINT`:如果Money列只需存储整数(如分单位),`BIGINT`支持大范围整数。 - **默认值处理**: - `DEFAULT 1000`或`DEFAULT 1000.00`语法正确,但需匹配数据类型(整数默认值用1000,小数用1000.00)。 - **数据库适配示例**: - **MySQL**: `Money DECIMAL(10,2) DEFAULT 1000.00` - **SQL Server**: `Money MONEY DEFAULT 1000`(内置`MONEY`类型可用) - **Oracle**: `Money NUMBER(10,2) DEFAULT 1000` **验证步骤**: 1. 在您的数据库工具中运行修改后的语句。 2. 如果仍有报错,检查数据库日志或错误消息:常见错误包括数据类型未定义或默认值格式问题(确保没有多余空格)。 3. 引用[2]中的`CHECK`约束示例提醒,您还可以添加约束如`CHECK (Money >= 0)`以验证值范围[^2]。 #### 注意事项 - **性能考虑**:使用`DECIMAL`比`BIGINT`稍慢,但保证精度;如果存储大型数据集,优先选择`DECIMAL`。 - **动态SQL参考**:引用[3]涉及MyBatis的动态SQL,虽不直接相关,但提醒您在应用层(如Java)生成SQL时,确保数据类型正确传递[^3]。 - 如果您提供具体的数据库系统(如MySQL或Oracle),我可以给出更精确的语法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值