浅谈postgresql数据库varchar、char、text的⽐较
如下所⽰:
名字描述
character varying(n), varchar(n)变长,有长度限制
character(n), char(n)定长,不⾜补空⽩
text变长,⽆长度限制
简单来说,varchar的长度可变,⽽char的长度不可变,对于postgresql数据库来说varchar和char的区别仅仅在于前者是变长,⽽后者是定长,最⼤长度都是10485760(1GB)
varchar不指定长度,可以存储最⼤长度(1GB)的字符串,⽽char不指定长度,默认则为1,这点需要注意。
text类型:在postgresql数据库⾥边,text和varchar⼏乎⽆性能差别,区别仅在于存储结构的不同
对于char的使⽤,应该在确定字符串长度的情况下使⽤,否则应该选择varchar或者text
官⽅解读:
SQL定义了两种基本的字符类型:character varying(n) 和character(n),这⾥的n 是⼀个正整数。两种类型都可以存储最多n个字符的字符串(没有字节)。试图存储更长的字符串到这些类型的字段⾥会产⽣⼀个错误,除⾮超出长度的字符都是空⽩,这种情况下该字符串将被截断为最⼤长度。这个看上去有点怪异的例外是SQL标准要求的。如果要存储的字符串⽐声明的长度短,类型为character的数值将会⽤空⽩填满;⽽类型为character varying的数值将只是存储短些的字符串。
如果我们明确地把⼀个数值转换成character varying(n) 或character(n),那么超长的数值将被截断成n 个字符,且不会抛出错误。这也是SQL标准的要求。
varchar(n)和char(n) 分别是character varying(n) 和character(n)的别名,没有声明长度的character等于character(1);如果不带长度说明词使⽤character varying,那么该类型接受任何长度的字符串。后者是PostgreSQL的扩展。
另外,PostgreSQL提供text类型,它可以存储任何长度的字符串。尽管类型text不是SQL 标准,但是许多其它SQL数据库系统也有它。
character类型的数值物理上都⽤空⽩填充到指定的长度n,并且以这种⽅式存储和显⽰。不过,填充的
空⽩是⽆语意的。在⽐较两个character 值的时候,填充的空⽩都不会被关注,在转换成其它字符串类型的时候, character值⾥⾯的空⽩会被删除。请注意,在character varying和text数值⾥,结尾的空⽩是有语意的。并且当使⽤模式匹配时,如LIKE,使⽤正则表达式。
⼀个简短的字符串(最多126个字节)的存储要求是1个字节加上实际的字符串,其中包括空格填充的character。更长的字符串有4个字节的开销,⽽不是1。长的字符串将会⾃动被系统压缩,因此在磁盘上的物理需求可能会更少些。更长的数值也会存储在后台表⾥⾯,这样它们就不会⼲扰对短字段值的快速访问。不管怎样,允许存储的最长字符串⼤概是1GB 。允许在数据类型声明中出现的n 的最⼤值⽐这还⼩。修改这个⾏为没有什么意义,因为在多字节编码下字符和字节的数⽬可能差别很⼤。如果你想存储没有特定上限的长字符串,那么使⽤text 或没有长度声明的character varying,⽽不要选择⼀个任意长度限制。
提⽰:这三种类型之间没有性能差别,除了当使⽤填充空⽩类型时的增加存储空间,和当存储长度约束的列时⼀些检查存⼊时长度的额外的CPU周期。虽然在某些其它的数据库系统⾥,character(n) 有⼀定的性能优势,但在PostgreSQL⾥没有。事实上,character(n)通常是这三个中最慢的,因为额外存储成本。在⼤多数情况下,应该使⽤text 或character varying。
补充:使⽤PostGreSQL数据库进⾏text录⼊和text检索
中⽂分词
ChineseParse.cs
using System;
using System.Collections;
using System.IO;
using System.Text.RegularExpressions;
namespace FullTextSearch.Common
{
/// <summary>
/// 中⽂分词器。
/// </summary>
public class ChineseParse
{
private static readonly ChineseWordsHashCountSet _countTable;
static ChineseParse()
{
_countTable = new ChineseWordsHashCountSet();
InitFromFile("");
}
/// <summary>
/// 从指定的⽂件中初始化中⽂词语字典和字符串次数字典。
/// </summary>
/
// <param name="fileName">⽂件名</param>
private static void InitFromFile(string fileName)
{
string path = Path.Combine(Directory.GetCurrentDirectory(), @"..\..\Common\", fileName);
if (File.Exists(path))
{
using (StreamReader sr = File.OpenText(path))
{
string s = "";
while ((s = sr.ReadLine()) != null)
{
ChineseWordUnit _tempUnit = InitUnit(s);
_countTable.InsertWord(_tempUnit.Word);
}
}
}
}
/// <summary>
/// 将⼀个字符串解析为ChineseWordUnit。
/// </summary>
/// <param name="s">字符串</param>
/// <returns>解析得到的ChineseWordUnit</returns>
/
// 4
/// 0
private static ChineseWordUnit InitUnit(string s)
{
var reg = new Regex(@"\s+");
string[] temp = reg.Split(s);
//if (temp.Length != 2)
//{
// throw new Exception("字符串解析错误:" + s);
//}
if (temp.Length != 1)
{
throw new Exception("字符串解析错误:" + s);
}
return new ChineseWordUnit(temp[0], Int32.Parse("1"));
}
/// <summary>
/// 分析输⼊的字符串,将其切割成⼀个个的词语。
/// </summary>
/// <param name="s">待切割的字符串</param>
/// <returns>所切割得到的中⽂词语数组</returns>
public static string[] ParseChinese(string s)
{
int _length = s.Length;
string _temp = String.Empty;
var _words = new ArrayList();
for (int i = 0; i < s.Length;)
{
_temp = s.Substring(i, 1);
if (_countTable.GetCount(_temp) > 1)
{
int j = 2;
for (; i + j < s.Length + 1 && _countTable.GetCount(s.Substring(i, j)) > 0; j++)
{
}
_temp = s.Substring(i, j - 1);
i = i + j - 2;
}
i++;
_words.Add(_temp);
}
var _tempStringArray = new string[_words.Count];
_words.CopyTo(_tempStringArray);
return _tempStringArray;
}
}
}
ChineseWordsHashCountSet.cs
using System.Collections;
namespace FullTextSearch.Common
{
/// <summary>
/// 记录字符串出现在中⽂字典所录中⽂词语的前端的次数的字典类。如字符串"中"出现在"中国"的前端,则在字典中记录⼀个次数。 /// </summary>
public class ChineseWordsHashCountSet
{
/// <summary>
/// 记录字符串在中⽂词语中出现次数的Hashtable。键为特定的字符串,值为该字符串在中⽂词语中出现的次数。
/// </summary>
private readonly Hashtable _rootTable;
/// <summary>
/// 类型初始化。
/// </summary>
public ChineseWordsHashCountSet()
{
_rootTable = new Hashtable();
}
/// <summary>
/// 查询指定字符串出现在中⽂字典所录中⽂词语的前端的次数。
/// </summary>
/// <param name="s">指定字符串</param>
/// <returns>字符串出现在中⽂字典所录中⽂词语的前端的次数。若为-1,表⽰不出现。</returns> public int GetCount(string s)
{
if (!_rootTable.ContainsKey(s.Length))
{
return -1;
}
var _tempTable = (Hashtable) _rootTable[s.Length];
if (!_tempTable.ContainsKey(s))
{
return -1;
}
return (int) _tempTable[s];
}
/// <summary>
/// 向次数字典中插⼊⼀个词语。解析该词语,插⼊次数字典。
/// </summary>
/// <param name="s">所处理的字符串。</param>
public void InsertWord(string s)
{
for (int i = 0; i < s.Length; i++)
{
string _s = s.Substring(0, i + 1);
InsertSubString(_s);
}
}
/// <summary>
/// 向次数字典中插⼊⼀个字符串的次数记录。
/// </summary>
/// <param name="s">所插⼊的字符串。</param>
private void InsertSubString(string s)
{
if (!_rootTable.ContainsKey(s.Length) && s.Length > 0)
{
var _newHashtable = new Hashtable();
_rootTable.Add(s.Length, _newHashtable);
}
var _tempTable = (Hashtable) _rootTable[s.Length];
if (!_tempTable.ContainsKey(s))
{
_tempTable.Add(s, 1);
}
else
{
_tempTable[s] = (int) _tempTable[s] + 1;
}
}
}
}
ChineseWordUnit.cs
namespace FullTextSearch.Common
{
public struct ChineseWordUnit
{
private readonly int _power;
private readonly string _word;
/// <summary>
/// 结构初始化。
/// </summary>
/// <param name="word">中⽂词语</param>
/// <param name="power">该词语的权重</param>
public ChineseWordUnit(string word, int power)
{
_word = word;
_power = power;
}
/// <summary>
/// 中⽂词语单元所对应的中⽂词。
/// </summary>
public string Word
{
get { return _word; }
}
/// <summary>
/
// 该中⽂词语的权重。
/// </summary>
public int Power
{
get { return _power; }
}
}
}
<
主窗体界⾯
MainManager.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using FullTextSearch.Common;
using Npgsql;
namespace FullTextSearch
{
public partial class MainManager : Form
{
private readonly PostgreSQL pg = new PostgreSQL();
private readonly SQLquerys sqlQuerys = new SQLquerys();
private char analysisType;
private string createConnString = "";
private DataSet dataSet = new DataSet();
private DataTable dataTable = new DataTable();
private char odabirAndOr;
private char vrstaPretrazivanja;
public MainManager()
{
InitializeComponent();
rbtn_AND.Checked = true;
rbtnNeizmjenjeni.Checked = true;
odabirAndOr = '*';
radioButton_Day.Checked = true;
radioButton_Day.Checked = true;
}
private void Form1_Load(object sender, EventArgs e)
{
gb_unosPodataka.Enabled = false;
groupBox_Search.Enabled = false;
groupBox_Analysis.Enabled = false;
button_Disconnect.Enabled = false;
button_Pretrazi.BackColor = Color.WhiteSmoke;
button_Disconnect.BackColor = Color.WhiteSmoke;
button_unosTekstaUBazu.BackColor = Color.WhiteSmoke;
button1.BackColor = Color.WhiteSmoke;
}
private void button_unosTekstaUBazu_Click(object sender, EventArgs e) {
string searchTextBoxString = rTB_unosTextaUBazu.Text;
if (searchTextBoxString != "")
{
pg.insertIntoTable(searchTextBoxString, pg.conn);
MessageBox.Show(searchTextBoxString + " 添加到数据库!");
rTB_unosTextaUBazu.Clear();
}
else
{
MessageBox.Show("不允许空数据!");
}
}
private void button_Pretrazi_Click(object sender, EventArgs e)
{
string stringToSearch;
string sql;
string highlitedText;
string rank;
string check;
stringToSearch = txt_Search.Text.Trim();
var list = new List<string>(ChineseParse.ParseChinese(stringToSearch)); ;
sql = ateSqlString(list, odabirAndOr, vrstaPretrazivanja);
richTextBox1.Text = sql;
check = stIfEmpty(stringToSearch);
pg.insertIntoAnalysisTable(stringToSearch, pg.conn);
pg.openConnection();
var command = new NpgsqlCommand(sql, pg.conn);
NpgsqlDataReader reader = command.ExecuteReader();
int count = 0;
linkLabel_Rezultat.Text = " ";
while (reader.Read())
{
highlitedText = reader[1].ToString();
rank = reader[3].ToString();
linkLabel_Rezultat.Text += highlitedText + "[" + rank + "]\n";
count++;
}
labelBrojac.Text = "到的⽂件数量: " + count;
pg.closeConnection();
}
private void rbtn_AND_CheckedChanged(object sender, EventArgs e)
{
odabirAndOr = '*';
}
private void rbtn_OR_CheckedChanged(object sender, EventArgs e)
{
odabirAndOr = '+';
}
private void rbtnNeizmjenjeni_CheckedChanged(object sender, EventArgs e) {
vrstaPretrazivanja = 'A';
}
private void rbtn_Rijecnici_CheckedChanged(object sender, EventArgs e) {
vrstaPretrazivanja = 'B';
}
private void rbtn_Fuzzy_CheckedChanged(object sender, EventArgs e)
{
vrstaPretrazivanja = 'C';
}
private void button_Connect_Click(object sender, EventArgs e)
{
if (connectMe())
{
gb_unosPodataka.Enabled = true;
groupBox_Search.Enabled = true;
groupBox_Analysis.Enabled = true;
textBox_Database.Enabled = false;
textBox_IP.Enabled = false;
textBox_Port.Enabled = false;
textBox_Password.Enabled = false;
textBox_UserID.Enabled = false;
字符串是什么类型的button_Connect.Enabled = false;
button_Disconnect.Enabled = true;
button_Pretrazi.BackColor = Color.SkyBlue;
button_Disconnect.BackColor = Color.IndianRed;
button_unosTekstaUBazu.BackColor = Color.MediumSeaGreen;
button1.BackColor = Color.MediumSeaGreen;
button_Connect.BackColor = Color.WhiteSmoke;
}
}
private void button_Disconnect_Click(object sender, EventArgs e)
{
gb_unosPodataka.Enabled = false;
groupBox_Search.Enabled = false;
groupBox_Analysis.Enabled = false;
textBox_Database.Enabled = true;
textBox_IP.Enabled = true;
textBox_Port.Enabled = true;
textBox_Password.Enabled = true;
textBox_UserID.Enabled = true;
button_Connect.Enabled = true;
button_Disconnect.Enabled = false;
button_Pretrazi.BackColor = Color.WhiteSmoke;
button_Disconnect.BackColor = Color.WhiteSmoke;
button_unosTekstaUBazu.BackColor = Color.WhiteSmoke;
button1.BackColor = Color.WhiteSmoke;
button_Connect.BackColor = Color.MediumSeaGreen;
txt_Search.Text = "";
linkLabel_Rezultat.Text = "";
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论